領先一步
VMware 提供培訓和認證,助您加速進步。
瞭解更多Spring Cloud 最有趣的特性之一是其可擴充套件性。您可以擴充套件它以支援其他雲、增強已支援的雲、支援新服務、新服務聯結器——所有這些都無需修改 Spring Cloud 程式碼本身。在本部落格中,我們將探討此功能。如果您還沒有這樣做,請閱讀本系列的第一篇和第二篇部落格,以獲取足夠的背景知識。
Spring Cloud 在三個正交方向上提供了可擴充套件性。您可以沿其中一個方向擴充套件它,而正交性確保您能繼續受益於其他方向。
雲平臺:雖然 Spring Cloud 支援 Cloud Foundry、Heroku 和本地配置雲(用於在類似雲的環境中進行本地測試),但您不受這些選擇的限制。您可以新增自己的雲平臺,並利用 Spring Cloud 的其他功能,例如 Spring Java Config。
雲服務:雲平臺提供各種服務,從關係型資料庫到訊息傳遞。每個雲平臺提供的服務差異很大,即使是同一平臺的多個安裝也是如此。對於 PaaS 產品(如 Cloud Foundry)來說尤其如此,Cloud Foundry 的私有例項往往具有特定於每個安裝的服務。Spring Cloud 提供了一種簡單的方法來擴充套件其核心產品之外的服務。就像雲平臺的可擴充套件性一樣,您無需更改 Spring Cloud 程式碼即可將其擴充套件到新服務,並且您可以繼續利用其他部分。
框架:Spring Cloud 目前透過 spring-service-connector 模組支援 Spring 框架。但是,除了該模組之外,Spring Cloud 中的任何部分都不依賴於 Spring。因此,您應該能夠使用任何基於 JVM 的框架的其他部分,或者透過新增新模組來擴充套件它以支援某個框架。
在上一篇部落格中,我們探討了如何使用 CloudFactory 和 Cloud 以程式設計方式使用 Spring Cloud。在可擴充套件性方面,您將不會使用這些,而是將在核心模組中實現其他型別。讓我們來看看它們。
要將 Spring Cloud 擴充套件到新的雲平臺,您需要熟悉的主要型別是 CloudConnector,它是一個簡單的三方法介面
public interface CloudConnector {
boolean isInMatchingCloud();
ApplicationInstanceInfo getApplicationInstanceInfo();
List<ServiceInfo> getServiceInfos();
}
isInMatchingCloud() 方法應該檢查其環境以確定它是否在正確的環境中執行。例如,Cloud Foundry 聯結器檢查 VCAP_APPLICATION 環境變數是否存在,而 Heroku 聯結器則檢查 DYNO 環境變數是否存在。getApplicationInstanceInfo() 方法返回當前應用程式例項的資訊(應用程式名稱、主機、埠和應用程式屬性)。最有趣的方法 getServiceInfos() 返回一個列表,其中每個元素包含足夠的資訊,以便應用程式知道如何連線到每個服務。每個 ServiceInfo 物件中包含的確切資訊取決於每個實現(ServiceInfo 本身只定義一個方法:getId())。
建立 CloudConnector 的實現後,您需要讓 Spring Cloud 瞭解它。對於所有擴充套件點,Spring Cloud 使用基於 ServiceLoader 的統一機制。應用於 Spring Cloud 的平臺可擴充套件性,它歸結為包含一個名為 /META-INF/services/org.springframework.cloud.CloudConnector 的檔案,其中包含一個帶有實現類的完全限定名稱的條目。通常,您會將此檔案與您的實現和支援類捆綁在一起。然後,應用程式所要做的就是將此 jar 包含在類路徑中。
ServiceInfoCreator 介面提供了一個擴充套件點,用於處理新服務。
public interface ServiceInfoCreator<SI extends ServiceInfo, SD> {
public boolean accept(SD serviceData);
public SI createServiceInfo(SD serviceData);
}
泛型引數 SI 定義了它將建立的 ServiceInfo 型別,而 SD 引數定義了它可以使用的原始服務資料型別。原始服務資料型別取決於雲平臺。例如,在 Cloud Foundry 中,它將是基於 VCAP_SERVICES 環境變數的 Map,而在 Heroku 中,它將是包含服務特定環境變數及其值的對。由於原始資料型別取決於平臺,因此 ServiceInfoCreator 的實現也取決於平臺。accept() 方法檢查服務資料並確定它是否可以處理它。例如,它可以檢視 URL 方案並確定它是否可以消費該服務資料。如果可以,createServiceInfo() 必須返回一個 ServiceInfo 物件。如果它是一個全新的服務,您可能還需要為它實現 ServiceInfo,否則您可以使用現有的服務。
一旦您實現了 ServiceInfoCreator,您將不得不讓 Spring Cloud 知道它。這遵循了與前面討論的雲平臺可擴充套件性相同的思路。在這種情況下,您使用的檔名取決於 CloudConnector。對於 Cloud Foundry,它是 /META-INF/services/org.springframework.cloud.cloudfoundry.CloudFoundryServiceInfoCreator(理論上,CloudConnector 實現可能決定使用其他擴充套件機制,但 Spring Cloud 不推薦這樣做)。
正如上一篇部落格中討論的,雲應用開發人員可能會決定直接使用 ServiceInfo 物件。因此,如果您只實現一個 ServiceInfoCreator,您就已經提供了一些好處。然而,許多專注於開發應用程式的開發人員可能不喜歡使用原始的 ServiceInfo 物件,因此您還需要實現下一個擴充套件。
最後一個擴充套件點是 ServiceConnectorCreator。它的作用是將 ServiceInfo 轉換為適合應用程式使用的框架的服務聯結器。例如,它可以將 MysqlServiceInfo 轉換為 DataSource 物件。Spring Cloud 開箱即用地支援 DataSource 以及一些 Spring Data 和 Spring AMQP 型別的聯結器。如果您希望將 Spring Cloud 擴充套件到其他框架,或者如果您想支援 Spring Cloud 尚未直接支援的其他 Spring Data 型別(如 Neo4J、Elasticsearch、Cassandra)或 Spring 相容型別(如 S3),這就是您需要的擴充套件點。
public interface ServiceConnectorCreator<SC, SI extends ServiceInfo> {
SC create(SI serviceInfo, ServiceConnectorConfig serviceConnectorConfig);
...
}
還有幾個方法;但是,您通常會擴充套件負責實現這些方法的 AbstractServiceConnectorCreator。
ServiceConnectorCreator 的 SC 泛型引數繫結到它將建立的聯結器型別,例如 DataSource,而 SI 引數表示它可以使用的 ServiceInfo 型別。
create() 方法提供一個 ServiceInfo 物件和一個配置物件,該物件攜帶服務特定的資訊,例如連線池引數。它需要使用這些引數來建立適當的聯結器。
一旦實現完成,只需將其放入名為 /META-INF/services/org.springframework.cloud.service.ServiceConnectorCreator 的檔案中。Spring Cloud 將使用前面描述的 Service Loader 機制。
如您所見,Spring Cloud 在雲平臺、服務和框架軸上提供了強大的可擴充套件性。下次,當您遇到這些新型別時,您應該能夠擴充套件 Spring Cloud 以便與它們一起工作。如果您將您的擴充套件開源,請告訴我們,以便我們可以展示它,讓其他人受益。如果它是一個足夠常見的擴充套件,請考慮提交拉取請求。