譯者 | 李睿
審校 | 孫淑娟 ?
如果用戶想在公共云基礎設施上運行JAVA微服務,那么可以利用多個云區域。這是一個好主意,其中有幾個原因。?
首先,由于硬件問題、云服務升級后引入的錯誤或人為錯誤,云計算可用區(Availability Zones)和云區域(Regions)經常出現故障。最著名的S3中斷之一是因為AWS公司的員工發布了錯誤的操作命令。?
如果一個云區域發生故障,那么該區域的微服務也會發生故障。但是,如果跨多個云區域運行微服務實例,即使美國東部地區出現大面積故障,也可以繼續運行。?
其次,用戶可以選擇在美國東部部署微服務,但應用程序在大西洋彼岸的歐洲運行。從歐洲用戶到美國東部應用程序實例的往返延遲大約為100毫秒,將這個時間與來自美國東部(運行微服務的數據中心附近)的用戶流量的5毫秒往返延遲進行比較,當歐洲用戶表示應用程序速度較慢時,不要感到驚訝。如果微服務實例部署在美國東部和歐洲西部地區,就不會聽到這種負面反饋。?
最后,假設一個Java微服務服務于來自歐洲的用戶請求,但從美國的數據庫實例請求數據。在這種情況下,可能會違反數據駐留法規(如果GDPR法規將請求的數據分類為個人數據)。然而,如果微服務實例在歐洲運行,并從歐洲某個云區域的數據庫實例獲取個人數據,那么就不會遇到監管機構所關注的問題。?
以下對本文的主題進行介紹,但希望看到在多個云區域運行Java微服務的一些好處。以下了解如何使用Spring Cloud開發和部署多個云區域微服務。?
高層次的概念?
以下以一個地理分布式Java Messenger為例,對微服務和Spring Cloud如何在多個云區域環境中發揮作用進行深入了解。?
該應用程序(由多個微服務組成)運行在多個云區域:美國西部、美國中部、歐洲西部和亞洲南部。所有應用程序實例都是無狀態的。?
Spring Cloud組件在應用程序實例所在的相同云區域中運行。該應用程序使用Spring Config Server進行配置設置分發,使用Spring Discovery Server進行平滑和容錯的服務間通信。?
選擇YugabyteDB作為分布式數據庫,可以輕松地遠程運行。另外,只要它是在PostgreSQL源代碼上構建的,它就自然地與Spring Data和Spring生態系統的其他組件集成在一起。本文并不會回顧YugabyteDB多區域部署選項。?
用戶流量通過全局外部云負載均衡器到達微服務實例。簡而言之,負載均衡器提供了一個單一的IP地址,可以從地球上的任何地點訪問。該IP地址(或轉換為該地址的DNS名稱)被提供給用戶的Web或移動前端,它們使用該IP連接到應用程序后端。負載均衡器自動將用戶請求轉發到最近的應用程序實例。下面將詳細地演示這個云組件。?
目標架構?
多區域Java Messenger的目標架構如下所示:?
整個解決方案運行在谷歌云平臺上。用戶可能更喜歡另一個云計算提供商提供的云服務,所以可以放心使用。很多用戶喜歡使用谷歌云,因為它提供了開發人員體驗、豐富且價格合理的基礎設施、快速且穩定的網絡,以及在本文中提到的其他好處。?
微服務實例可以根據需要部署在盡可能多的云區域中。?
在上圖中有兩個隨機云區域:Region A和Region B。微服務實例可以運行在一個云區域的多個可用性分區中(例如Region A的Zone A和ZoneB),也可以運行在一個云區域內(Region B的Zone A)。?
每個云區域都有一個Spring Discovery和Config服務器的實例也是合理的,但特意為每個可用區運行每個服務器的實例,以將延遲降至最低。?
誰決定哪個微服務實例將服務于用戶請求?那全局外部負載均衡器就是決策者!?
假設一位用戶通過手機打開Java Messenger,并發送了一條消息。帶有消息的請求將被發送到負載均衡器,它可以通過以下方式轉發:?
(1)Region A是離用戶最近的云區域,并且在請求時處于正常狀態(沒有中斷)。負載均衡器根據這些條件選擇該區域。 ?
(2)在這個云區域中,微服務實例在Zone A和Zone B都可用。因此,如果這兩個可用區都處于活動狀態并且正常運行,負載均衡器可以選擇任何一個可用區。假設這個請求發送到Zone B。?
以下將解釋每個微服務負責什么。到目前為止,只需要知道消息傳遞微服務將所有應用程序數據(消息、通道、用戶配置文件等)存儲在一個多區域YugabyteDB部署中。Attachments微服務使用全球分布的谷歌云存儲存儲用戶圖片。 ?
微服務和Spring Cloud?
以下進一步討論微服務以及它們如何利用Spring Cloud。 ?
Messenger微服務實現了每個Messenger應用程序必須具備的跨渠道和工作區發送消息的關鍵功能。Attachments微服務上載圖片和其他文件,可以在geo messenger的存儲庫中查看它們的源代碼。?
Spring Cloud配置服務器?
這兩個微服務都是在Spring Boot上構建的。當它們啟動時,他們從Spring Cloud Config Server中檢索配置設置,如果需要在分布式環境中外部化配置文件,這是一個很好的選項。?
配置服務器可以托管并從各種后端獲取配置,包括Git存儲庫、Vault和JDBC兼容數據庫。在Java geo messenger的情況下,使用Git選項,下面一行來自應用程序。兩個微服務請求的屬性文件Spring Boot從配置服務器加載設置:?
YAML ?
1spring.config.import=configserver:http://${CONFIG_SERVER_HOST}:${CONFIG_SERVER_PORT}?
- 1.
- 2.
Spring Cloud Discovery Server?
一旦啟動了Messenger和Attachments微服務,它們就會向Spring Cloud Discovery Server(屬于Spring Cloud.NETflix組件)的區域本地實例注冊。?
Discovery Server實例的位置在從Config Server實例傳輸的以下配置設置中定義:?
YAML ?
1eureka.client.serviceUrl.defaultZnotallow=http://${DISCOVERY_SERVER_HOST}:${DISCOVERY_SERVER_PORT}/eureka?
- 1.
- 2.
也可以在瀏覽器中打開HTTP地址,確認服務已成功注冊到Discovery Server:?
微服務使用您通過應用程序的spring.Application.name設置傳遞的名稱注冊到application.properties file。如上圖所示,選擇了以下名稱: ?
·spring.application.name=messenger for the Messenger microservice?
·spring.application.name=attachments for the Attachments service?
- 1.
- 2.
微服務實例使用這些名稱來定位并通過Discovery Server相互發送請求。例如,當用戶想要在討論頻道中上傳圖片時,該請求首先會發送到Messenger服務。然后,Messenger在Discovery Server的幫助下將此任務委托給Attachments微服務。?
首先,Messenger服務獲得一個附件對應的實例: ?
Java
List<ServiceInstance> serviceInstances = discoveryClient.getInstances("ATTACHMENTS");
ServiceInstance instance;
if (!serviceInstances.isEmpty()) {
instance = serviceInstances
.get(ThreadLocalRandom.current().nextInt(0, serviceInstances.size()));
}
System.out.printf("Connected to service %s with URI %sn",
instance.getInstanceId(), instance.getUri());
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
接下來,Messenger微服務使用附件的實例URI創建一個HTTP客戶端,并通過InputStream發送圖片: ?
Java
HttpClient httpClient = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(instance.getUri() + "/upload?fileName=" + fileName))
.header("Content-Type", mimeType)
.POST(HttpRequest.BodyPublishers.ofInputStream(new Supplier<InputStream>() {
@Override
public InputStream get() {
return inputStream;
}
})).build();
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
Attachments服務通過REST端點接收請求,并最終將圖片存儲在谷歌云存儲中,將圖片URL返回給Messenger微服務:?
Java
public Optional<String> storeFile(String filePath, String fileName, String contentType) {
if (client == null) {
initClient();
}
String objectName = generateUniqueObjectName(fileName);
BlobId blobId = BlobId.of(bucketName, objectName);
BlobInfo blobInfo = BlobInfo.newBuilder(blobId).build();
try {
client.create(blobInfo, Files.readAllBytes(Paths.get(filePath)));
} catch (IOException e) {
System.err.println("Failed to load the file:" + fileName);
e.printStackTrace();
return Optional.empty();
}
System.out.printf(
"File %s uploaded to bucket %s as %s %n", filePath, bucketName, objectName);
String objectFullAddress = "http://storage.googleapis.com/" + bucketName + "/" + objectName;
System.out.println("Picture public address: " + objectFullAddress);
return Optional.of(objectFullAddress);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
如果想探索微服務的完整實現以及它們如何通過Discovery Server進行通信,可以訪問GitHub repo。 ?
在谷歌云平臺上部署?
現在,在谷歌云平臺上跨三個地理位置和五個云區域部署Java geo-messenger:北美('us-west2','us-central1','us-east4'),歐洲('Europe-west3')和亞洲('Asia-east1')。 ?
遵循以下步驟部署:?
(1)創建一個谷歌項目。 ?
(2)創建自定義高級網絡。 ?
(3)配置谷歌云存儲。 ?
(4)為虛擬機創建實例模板。 ?
(5)以應用實例啟動虛擬機。 ?
(6)配置全局外部負載均衡器。?
將跳過上述步驟的詳細說明。與其相反,采用下圖來闡明為什么在步驟2中選擇高級谷歌網絡:?
假設一個應用程序實例部署在美國的谷歌云平臺上,用戶從印度連接到該應用程序。從用戶的位置到應用程序有快速路徑和慢速路徑。?
如果為這個部署選擇了標準網絡,則采用慢速路徑。在這種情況下,用戶請求通過公共互聯網傳輸,在到達美國之前進入和退出許多云計算提供商的網絡。最終,在美國,請求到達靠近應用程序實例的谷歌的PoP(存在點),進入谷歌網絡,并到達應用程序。 ?
如果部署使用高級網絡,則選擇快速路徑。在這種情況下,用戶請求在離用戶最近的PoP處進入谷歌網絡,并且永遠不會離開它。該PoP在印度,請求將通過快速穩定的連接加速到美國的應用程序實例。另外,云外部負載均衡器需要高級層。否則,將無法在最近的PoP處攔截用戶請求,并將它們轉發到附近的應用程序實例。 ?
測試容錯性?
一旦微服務部署到全球各大洲,就可以看到云負載均衡器在正常時間和停機期間的工作情況。?
在瀏覽器中打開負載均衡器使用的IP地址,并在其中一個討論通道中發送一些帶有照片的消息:?
Messenger和Attachments微服務的哪個實例為最后請求提供了服務?這取決于在世界上的位置。在本文的例子中,來自美國東部(ig-us-east)的實例服務于流量: ?
如果美國東部地區無法使用,導致該地區的所有微服務都無法使用,應用程序將會發生什么? ?
對于多區域部署來說不是問題。負載均衡器將檢測美國東部的問題,并將流量轉發到另一個最近的位置。在這種情況下,只要住在大西洋附近的美國東海岸,流量就會被轉發到歐洲:?
為了模擬美國東部地區的停機,連接到該地區的虛擬機并關閉了所有的微服務。負載均衡器檢測到該區域的微服務不再響應,并開始將流量轉發到歐洲數據中心。?
現在可以享受開箱即用的容錯功能! ?
測試性能?
除了容錯之外,如果跨多個云區域部署Java微服務,那么無論用戶請求位于何處,應用程序都能夠以較低的延遲服務用戶請求。 ?
為了實現這一點,首先,需要在大多數用戶所在的云區域部署微服務實例,并配置全局外部負載均衡器,可以進行路由。這就是在“跨多個云區域自動化Java應用程序部署”一文中討論的內容。 ?
其次,需要在這些位置正確地排列數據。數據庫需要跨多個區域運行,與微服務實例一樣。否則,微服務和數據庫之間的延遲會很高,整體性能會很差。?
在討論的架構中,使用了YugabyteDB,因為它是一個分布式SQL數據庫,可以跨多個云區域部署。?
結語?
如果為公共云環境開發Java應用程序,則應該通過跨多個區域部署應用程序實例來利用全球云計算基礎設施。這將使解決方案更具彈性、性能更高,并符合數據監管要求。 ?
重要的是要記住,創建跨云區域運行和協調的微服務并不難。Spring生態系統提供了Spring Cloud框架,而像谷歌這樣的公共云提供商提供了簡化工作所需的基礎設施和服務。?
原文標題:??Run Java Microservices Across Multiple Cloud Regions With Spring Cloud??,作者:Denis Magda