領先一步
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 以便與之協作。如果您將擴充套件開源,請告知我們,以便我們可以展示它以使其他人受益。如果它是足夠常見的擴充套件,請考慮提交拉取請求。