如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

當您進行大規模設計和構建應用程序時,您將面臨兩個重大挑戰:可伸縮性和健壯性。

您應該精心設計您的服務,即使它受到間歇性重載,它仍然可靠地運行。以蘋果商店為例,每年都有數百萬的Apple客戶預先註冊購買新的iPhone,這是數百萬人同時購買物品,蘋果商店流量如果描述為每秒的請求數量,那麼在下午6點到8點之間是有峰值最高峰。

現在想象一下,你的任務是構建這樣的應用程序。

  • 您正在建立一個商店,用戶可以在那裡購買自己喜歡的商品。
  • 您構建一個微服務來呈現網頁並提供靜態資產。您還構建了一個後端REST API來處理傳入的請求。
  • 您希望將兩個組件分開,因為使用相同的REST API,您可以為網站和移動應用程序提供服務。

你的商店上線了!

您決定將應用程序擴展為前端的四個實例和後端的四個實例,因為您預測網站比平常更繁忙。網站開始接收越來越多的流量。

前端服務正在處理繁忙流量。但是您注意到連接到數據庫的後端正在努力跟上事務的數量,不用擔心,您可以將後端的服務器數量擴展到8個實例。

收到的流量更多,後端無法應對。

一些服務開始丟棄連接。憤怒的客戶與您的客戶服務取得聯繫。而現在你被淹沒在大流量中,你的後端無法應付這種大流量,失去了很多連接。電子商務網站丟失連接就是丟失交易,就是收入損失。

您的應用程序並非設計為健壯且高度可用:

  • 前端和後端緊密耦合 - 實際上它不能在沒有後端的情況下處理應用程序
  • 前端和後端必須一致擴展 - 如果沒有足夠的後端,你可能會淹沒在流量中
  • 如果後端不可用,則無法處理傳入的事務。

您可以重新設計體系結構,以便將前端和後端與隊列分離:

前端將消息發佈到隊列,而後端則一次處理一個待處理消息。

新架構有一些明顯的好處:

  • 如果後端不可用,則隊列充當緩衝區
  • 如果前端產生的消息多於後端可以處理的消息,則這些消息將緩衝在隊列中
  • 您可以獨立於前端擴展後端 - 即您可以擁有數百個前端服務和後端的單個實例

太好了,但是你如何構建這樣的應用程序?您如何設計可處理數十萬個請求的服務?您如何部署動態擴展的應用程序?在深入瞭解部署和擴展的細節之前,讓我們關注應用程序。

編寫Spring應用程序

現在服務有三個組件:前端,後端和消息代理。

前端是一個簡單的Spring Boot Web應用程序,帶有Thymeleaf模板引擎;後端是一個消耗隊列消息的工作者。由於Spring Boot與JSM具有出色的集成,因此您可以使用它來發送和接收異步消息。您可以在learnk8s / spring-boot-k8s-hpa中找到一個連接到JSM的前端和後端應用程序的示例項目。

請注意,該應用程序是用Java 10編寫的,才能利用改進的Docker容器集成。只有一個代碼庫,您可以將項目配置為作為前端或後端運行。

您應該知道該應用程序具有:

  • 你可以購買物品的主頁
  • 管理面板,您可以在其中檢查隊列中的消息數
  • /health當應用程序準備好接收流量時發出信號的端點
  • /submit從表單接收提交併在隊列中創建消息的端點
  • 一個/metrics端點,以露出待處理的消息的數量在隊列中(以後會更多)

該應用程序可以在兩種模式下運行:

  1. 作為前端,應用程序呈現人們可以購買物品的網頁。
  2. 作為工作者,應用程序等待隊列中的消息並處理它們。

請注意,在示例項目中,通過等待五秒來模擬處理Thread.sleep(5000)。您可以通過更改application.yaml為您的值來配置任一模式的應用程序。

運行應用程序

默認情況下,應用程序作為前端和工作程序啟動。您可以運行該應用程序,只要您在本地運行ActiveMQ實例,您就應該能夠購買物品並讓系統處理這些物品。

如果檢查日誌,則應該看到工作程序處理項目。

有效!編寫Spring Boot應用程序很容易。

一個更有趣的主題是學習如何將Spring Boot連接到消息代理。

使用JMS發送和接收消息

Spring JMS(Java消息服務)是一種使用標準協議發送和接收消息的強大機制。如果您以前使用過JDBC API,那麼您應該熟悉JMS API,因為它的工作方式類似。您可以使用JMS使用的最流行的消息代理是ActiveMQ - 一個開源消息服務器。使用這兩個組件,您可以使用熟悉的接口(JMS)將消息發佈到隊列(ActiveMQ),並使用相同的接口來接收消息。更妙的是,Spring Boot與JMS的集成非常好,因此您可以立即加快速度。

實際上,以下短類封裝了用於與隊列交互的邏輯:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

您可以使用該send方法將消息發佈到命名隊列。此外,Spring Boot將為onMessage每個傳入消息執行該方法。

最後一個難題是如何讓Spring Boot使用該類。您可以通過在Spring Boot應用程序中註冊偵聽器來在後臺處理消息,如下所示:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

其中id是使用者的唯一標識符,destination是隊列的名稱。

部署

驗證了應用程序的工作原理,現在是時候部署它了。您可以啟動VPS,安裝Tomcat,並花些時間製作自定義腳本來測試,構建,打包和部署應用程序。或者您可以編寫您希望擁有的描述:一個消息代理和兩個使用負載均衡器部署的應用程序。

Kubernetes之類的協調器可以閱讀您的願望清單並提供正確的基礎設施,花在基礎架構上的時間減少意味著更多的時間編碼,這次你將把應用程序部署到Kubernetes。但在開始之前,您需要一個Kubernetes集群。

您可以註冊Google雲平臺或Azure,並使用雲提供商Kubernetes提供的服務。或者,您可以在將應用程序移動到雲之前在本地嘗試Kubernetes。

minikube是一個打包為虛擬機的本地Kubernetes集群。如果您使用的是Windows,Linux和Mac,那就太好了,因為創建群集需要五分鐘。

您還應該安裝kubectl客戶端以連接到您的群集。

你可以找到關於如何安裝的說明minikube,並kubectl從官方文檔。如果您在Windows上運行,則應查看有關如何安裝Kubernetes和Docker的詳細指南。

啟動一個具有8GB RAM和一些額外配置的集群:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

請注意,如果您使用的是預先存在的minikube實例,則可以通過銷燬VM來重新調整VM的大小。只是添加--memory 8096將不會有任何影響。

驗證安裝是否成功。您應該看到列為表的一些資源。集群已經準備就緒,也許您應該立即開始部​​署?

還沒。

你必須先裝好你的東西。

部署到Kubernetes的應用程序必須打包為容器。畢竟,Kubernetes是一個容器協調器,所以它本身無法運行你的jar。容器類似於fat jar:它們包含運行應用程序所需的所有依賴項。甚至JVM也是容器的一部分。所以他們在技術上是一個更胖的fat-jar。

Docker

將應用程序打包為容器的流行技術是Docker。如果您沒有安裝Docker,可以按照Docker官方網站上的說明進行操作。

直接在minikube創建容器圖像。

先,按照此命令打印的說明連接Docker客戶端到minikube:

minikube docker-env

請注意,如果切換終端,則需要在minikube重新連接到內部的Docker守護程序。每次使用不同的終端時都應遵循相同的說明。

從項目的根目錄構建容器圖像:

docker build -t spring-k8s-hpa .

可以驗證鏡像是否已構建並準備好運行:

docker images | grep spring

群集已準備好,您打包應用程序,可以要求Kubernetes部署應用程序。

部署到Kubernetes

您的應用程序有三個組件:

  • 呈現前端的Spring Boot應用程序
  • ActiveMQ作為消息代理
  • 處理事務的Spring Boot後端

您應該分別部署這三個組件。

對於他們每個人你應該創建:

  • 一個部署描述什麼容器部署和配置對象
  • 一個Service對象,充當Deployment部署創建的應用程序的所有實例的負載均衡器

部署中的每個應用程序實例都稱為Pod。

部署ActiveMQ

讓我們從ActiveMQ開始吧。

您應該創建一個activemq-deployment.yaml包含以下內容的文件:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

幸運的是,這個模板更短!

yaml解讀:

  • 您創建了一個公開端口61616的負載均衡器
  • 傳入流量將分發到具有類型標籤的所有Pod(請參閱上面的部署) app: queue
  • 這targetPort是Pods暴露的端口

您可以使用以下命令創建資源:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

您可以使用以下命令驗證數據庫的一個實例是否正在運行:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

部署前端

創建fe-deployment.yaml:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

署看起來很像以前的一個。

但是有一些新的字段:

  • 有一個section 可以注入環境變量
  • 還有liveness probe探針,可以告訴您應用程序何時可以接受流量

創建fe-service.yaml:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

使用下面命令創建k8s資源:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

可以使用以下命令驗證前端應用程序的一個實例是否正在運行:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

部署後端

創建backend-deployment.yaml:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

創建backend-service.yaml:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

創建者兩個資源:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

可以驗證後端的一個實例是否正在運行:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

部署完成。

它真的有效嗎?

您可以使用以下命令啟動,然後在瀏覽器中訪問該應用程序:

minikube service backend

minikube service frontend

手動擴展以滿足不斷增長的需求

單個工作程序可能無法處理大量消息。實際上,它當時只能處理一條消息。

如果您決定購買數千件物品,則需要數小時才能清除隊列。

此時您有兩個選擇:

  • 你可以手動放大和縮小
  • 您可以創建自動縮放規則以自動向上或向下擴展

讓我們先從基礎知識開始。

您可以使用以下方法將後端擴展為三個實例:

kubectl scale --replicas=5 deployment/backend

可以驗證Kubernetes是否創建了另外五個實例:

kubectl get pods

應用程序可以處理五倍以上的消息。

一旦消息隊列排空,您可以縮小:

kubectl scale --replicas=1 deployment/backend

如果您知道最多的流量何時達到您的服務,手動擴大和縮小都很棒。

如果不這樣做,設置自動縮放器允許應用程序自動縮放而無需手動干預。

您只需要定義一些規則。

公開應用程序指標

Kubernetes如何知道何時擴展您的應用?

很簡單,你必須告訴它。

自動調節器通過監控指標來工作。只有這樣,它才能增加或減少應用程序的實例。

因此,您可以將隊列長度公開為度量標準,並要求autoscaler觀察該值。隊列中的待處理消息越多,Kubernetes將創建的應用程序實例就越多。

那麼你如何公開這些指標呢?

應用程序有一個/metrics端點,用於公開隊列中的消息數。如果您嘗試訪問該頁面,您會注意到以下內容:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

應用程序不會將指標公開為JSON格式。格式為純文本,是公開Prometheus指標的標準。不要擔心記憶格式。大多數情況下,您將使用其中一個Prometheus客戶端庫。

在Kubernetes中使用應用程序指標

已準備好進行自動縮放 - 但您應首先安裝度量服務器。實際上,默認情況下,Kubernetes不會從您的應用程序中提取指標。如果您願意,可以啟用Custom Metrics API。

要安裝Custom Metrics API,您還需要Prometheus - 時間序列數據庫。安裝Custom Metrics API所需的所有文件都可以方便地打包在learnk8s / spring-boot-k8s-hpa中。

應下載該存儲庫的內容,並將當前目錄更改monitoring為該項目的文件夾。

cd spring-boot-k8s-hpa/monitoring

可以創建自定義指標API:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

應該等到以下命令返回自定義指標列表:

kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1" | jq .

任務完成!

您已準備好使用指標。

實際上,您應該已經找到了隊列中消息數量的自定義指標:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

恭喜,您有一個公開指標的應用程序和使用它們的指標服務器。

您最終可以啟用自動縮放!

在Kubernetes中進行自動擴展部署

Kubernetes有一個名為Horizo​​ntal Pod Autoscaler的對象,用於監視部署並上下調整Pod的數量。

您將需要其中一個來自動擴展實例。

您應該創建一個hpa.yaml包含以下內容的文件:

如何使用消息隊列、Spring Boot和Kubernetes擴展微服務

這個文件很神秘,所以讓我為你解釋一下:

  • 在scaleTargetRef指定Kubernetes監視的部署。在這種情況下,它是前面的worker部署。
  • 使用messages指標metrics來擴展您的Pod。當隊列中有超過十條消息時,Kubernetes將觸發自動擴展。
  • 至少,部署應該有兩個Pod。10 個Pods是上限。

創建資源:

kubectl create -f hpa.yaml

提交這個自動縮放器autoscaler後,您應該注意到後端的副本數量是兩個。這是有道理的,因為您要求自動縮放器始終至少運行兩個副本。

您可以檢查觸發自動縮放器的條件以及由此產生的事件:

kubectl describe hpa

自動縮放器autoscaler能夠將Pod數量擴展到2,並且它已準備好監視部署。

令人興奮的東西,但它有效嗎?

負載測試

只有一種方法可以知道它是否有效:在隊列中創建大量消息。

轉到前端應用程序並開始添加大量消息。在添加消息時,使用以下方法監視Horizo​​ntal Pod Autoscaler的狀態:

kubectl describe hpa

Pod的數量從2上升到4,然後是8,最後是10。

該應用程序隨消息數量而變化!歡呼!

您剛剛部署了一個完全可伸縮的應用程序,可根據隊列中的待處理消息數進行擴展。

另外,縮放算法如下:

MAX(CURRENT_REPLICAS_LENGTH * 2, 4)

在解釋算法時,文檔沒有多大幫助。您可以在代碼中找到詳細信息。

此外,每分鐘都會重新評估每個放大,而每兩分鐘縮小一次。

以上所有都是可以調整的設置。

但是你還沒有完成。

什麼比自動縮放實例更好?自動縮放集群。​​​​​​​

跨節點縮放Pod非常有效。但是,如果群集中沒有足夠的容量來擴展Pod,該怎麼辦?如果達到峰值容量,Kubernetes將使Pods處於暫掛狀態並等待更多資源可用。如果您可以使用類似於橫向Pod Autoscaler的自動縮放器,對於節點則會很棒。

您可以擁有一個集群自動縮放器,可以在您需要更多資源時為Kubernetes集群添加更多節點。集群自動縮放器具有不同的形式和大小。它也是由雲提供商指定的。

請注意,使用minikube您將無法使用自動縮放器進行測試,因為它根據定義是單節點。

概括

大規模設計應用程序需要仔細規劃和測試。

基於隊列的體系結構是一種出色的設計模式,可以解耦您的微服務並確保它們可以獨立擴展和部署。

雖然您可以部署部署腳本,但可以更輕鬆地利用容器協調器(如Kubernetes)自動部署和擴展應用程序。​​​​​​​

寫在最後:

歡迎留言討論,如需Java方面的架構資料,我這裡剛好有一份,怎麼領取→→→關注+轉發 然後私信“架構資料” 即可領取

點關注,不迷路,持續更新!!!


分享到:


相關文章: