Spring Cloud 系列之 Bus 消息總線

Spring Cloud 系列之 Bus 消息總線

1|0什麼是消息總線
消息代理中間件構建一個共用的消息主題讓所有微服務實例訂閱,當該消息主題產生消息時會被所有微服務實例監聽和消費。

消息代理又是什麼?消息代理是一個消息驗證、傳輸、路由的架構模式,主要用來實現接收和分發消息,並根據設定好的消息處理流來轉發給正確的應用。它在微服務之間起到通信調度作用,減少了服務之間的依賴。

2|0什麼是 Spring Cloud Bus

Spring Cloud Bus 是 Spring Cloud 體系內的消息總線,用來連接分佈式系統的所有節點。

Spring Cloud Bus 將分佈式的節點用輕量的消息代理(RibbitMQ、Kafka)連接起來。可以通過消息代理廣播配置文件的更改,或服務之間的通訊,也可以用於監控。解決了微服務數據變更,及時同步的問題。

官方文檔:https://cloud.spring.io/spring-cloud-static/spring-cloud-bus/2.2.1.RELEASE/reference/html/

3|0什麼時候使用 Spring Cloud Bus
微服務一般都採用集羣方式部署,而且在高併發下經常需要對服務進行擴容、縮容、上線、下線的操作。比如我們需要更新配置,又或者需要同時失效所有服務器上的某個緩存,需要向所有相關的服務器發送命令,此時就可以選擇使用 Spring Cloud Bus 了。

總的來說,就是在我們需要把一個操作散發到所有後端相關服務器的時候,就可以選擇使用 Spring Cloud Bus 了。

接下來我們通過 Spring Cloud Bus 實現微服務架構的配置刷新。

4|0環境準備
RibbitMQ v3.8.2 地址:192.168.10.101

bus-demo 聚合工程。SpringBoot 2.2.4.RELEASE、Spring Cloud Hoxton.SR1。

eureka-server:註冊中心
eureka-server02:註冊中心
config-server:配置中心服務端
config-server02:配置中心服務端
order-service:訂單服務(配置中心客戶端)
order-service02:訂單服務(配置中心客戶端)
配置文件 order-service-prod.yml

spring: application: name: order-service # 應用名稱 # 配置 Eureka Server 註冊中心 eureka: instance: prefer-ip-address: true # 是否使用 ip 地址註冊 instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port client: service-url: # 設置服務註冊中心地址 defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/ # 自定義配置 name: order-service-prod password: root

5|0Spring Cloud Bus 實現配置刷新
5|1客戶端發起通知
點擊鏈接觀看:客戶端發起通知視頻(獲取更多請關注公衆號「哈嘍沃德先生」)

消息總線(Bus)的典型應用場景就是配置中心客戶端刷新。

我們在學習 Spring Cloud Config 配置中心時給大家講了基於 Actuator 的配置刷新,當時的案例只有一個 Config Client,我們可以使用 Webhook,設置手動刷新都不算太費事,但是如果客戶端比較多的情況下,一個一個去手動刷新未免有點複雜,這種方案就不太適合了。使用 Spring Cloud Bus 可以完美解決這一問題。

藉助 Spring Cloud Bus 的廣播功能,讓 Config Client 都訂閱配置更新事件,當配置更新時,觸發其中一個端的更新事件,Spring Cloud Bus 就把此事件廣播到其他訂閱客戶端,以此來達到批量更新。

Webhook 監聽被觸發,給 ConfigClient A 發送 bus-refresh 請求刷新配置
ConfigClient A 讀取 ConfigServer 中的配置,並且發送消息給 Bus
Bus 接收消息後廣播通知其他 ConfigClient
其他 ConfigClient 收到消息重新讀取最新配置
添加依賴
Config Client 添加 spring cloud starter bus amqp 依賴。

org.springframework.cloudspring-cloud-starter-bus-amqp

配置文件
配置文件需要配置 消息隊列 和 bus-refresh 自動刷新端點。/actuator/bus-refresh 端點會清除 @RefreshScope緩存重新綁定屬性。

Config Client 的 bootstrap.yml 核心配置。

spring: cloud: config: name: order-service # 配置文件名稱,對應 git 倉庫中配置文件前半部分 label: master # git 分支 profile: prod # 指定環境 discovery: enabled: true # 開啓 service-id: config-server # 指定配置中心服務端的 service-id # 消息隊列 rabbitmq: host: 192.168.10.101 port: 5672 username: guest password: guest virtual-host: / # 度量指標監控與健康檢查 management: endpoints: web: base-path: /actuator # 訪問端點根路徑,默認爲 /actuator exposure: include: bus-refresh # 需要開啓的端點 #exclude: # 不需要開啓的端點

測試
查看端點
訪問:http://localhost:9091/actuator 可以看到已經開啓了 bus-refresh 自動刷新端點。

訪問:http://localhost:9091/namehttp://localhost:9092/name 結果如下:

修改 Git 倉庫配置
修改 Git 倉庫配置信息如下:

自定義配置 name: order-service-prod-1.0

自動刷新
刷新頁面發現結果並未改變,沒事正常。

通過 Post 方式調用「任意客戶端」的自動刷新端點:http://localhost:9091/actuator/bus-refresh 再次訪問結果如下:

查看隊列
再來觀察一下消息隊列的 UI 界面,發現多了一個 springCloudBus 的交換機。

該交換機下綁定了兩個隊列對應我們的兩個 Config Client。

客戶端發起通知缺陷
打破了微服務的職責單一性。微服務本身是業務模塊,它本不應該承擔配置刷新的職責。
破壞了微服務各節點的對等性。
存在一定的侷限性。例如,微服務在遷移時,它的網絡地址常常會發生變化,此時如果想要做到自動刷新,就不得不修改Webhook 的配置。
5|2服務端發起通知
點擊鏈接觀看:服務端發起通知視頻(獲取更多請關注公衆號「哈嘍沃德先生」)

爲了解決客戶端發起通知缺陷,我們改用服務端發起通知。

Webhook監聽被觸發,給 ConfigServer 發送 bus-refresh 請求刷新配置
ConfigServer 發送消息給 Bus
Bus 接收消息後廣播通知所有 ConfigClient
各 ConfigClient 收到消息重新讀取最新配置
添加依賴
Config Server 添加 spring cloud starter bus amqp 依賴。

org.springframework.cloudspring-cloud-starter-bus-amqp

配置文件
配置文件需要配置 消息隊列 和 bus-refresh 自動刷新端點。/actuator/bus-refresh 端點會清除 @RefreshScope緩存重新綁定屬性。

Config Server 的 application.yml 核心配置。

spring: application: name: config-server # 應用名稱 cloud: config: server: git: uri: https://github.com/imrhelloworld/config-repo # 配置文件所在倉庫地址 #username: # Github 等產品的登錄賬號 #password: # Github 等產品的登錄密碼 #default-label: master # 配置文件分支 #search-paths: # 配置文件所在根目錄 # 消息隊列 rabbitmq: host: 192.168.10.101 port: 5672 username: guest password: guest virtual-host: / # 配置 Eureka Server 註冊中心 eureka: instance: prefer-ip-address: true # 是否使用 ip 地址註冊 instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port client: service-url: # 設置服務註冊中心地址 defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/ # 度量指標監控與健康檢查 management: endpoints: web: base-path: /actuator # 訪問端點根路徑,默認爲 /actuator exposure: include: bus-refresh # 需要開啓的端點 #exclude: # 不需要開啓的端點

測試
查看端點
訪問:http://localhost:8888/actuator 可以看到已經開啓了 bus-refresh 自動刷新端點。

訪問:http://localhost:9091/namehttp://localhost:9092/name 結果如下:

修改 Git 倉庫配置
修改 Git 倉庫配置信息如下:

自定義配置 name: order-service-prod-2.0

自動刷新
刷新頁面發現結果並未改變,沒事正常。

通過 Post 方式調用「任意服務端」的自動刷新端點:http://localhost:8888/actuator/bus-refresh 再次訪問結果如下:

查看隊列
再來觀察一下消息隊列的 UI 界面,發現多了一個 springCloudBus 的交換機。

該交換機下綁定了四個隊列對應我們的兩個 Config Server 和兩個 Config Client。

5|3局部刷新
假設有這樣一種場景,我們開發了一個新的功能,此時需要對該功能進行測試。我們只希望其中一個微服務的配置被更新,等功能測試完畢,正式部署線上時再更新至整個集羣。但是由於所有微服務都受 Spring Cloud Bus 的控制,我們更新了其中一個微服務的配置,就會導致其他服務也被通知去更新配置。這時候局部刷新的作用就體現出來了。

刷新指定服務
修改 Git 倉庫配置信息如下:

自定義配置 name: order-service-prod-3.0

通過 Post 方式調用「任意服務端」的自動刷新端點:http://localhost:8888/actuator/bus-refresh/order-service:9091 再次訪問結果如下:

9091 端口的客戶端已經更新配置。

9092 端口的客戶端沒有更新配置。

刷新指定集羣
假設現在功能測試完畢,需要正式部署線上更新至整個集羣。但是由於 Spring Cloud Bus 控制着多個微服務集羣(訂單微服務、商品微服務等),而我們只想更新指定集羣下的配置,這個時候就可以使用 Bus 提供的通配符更新方案。

修改 Git 倉庫配置信息如下:

自定義配置 name: order-service-prod-4.0

通過 Post 方式調用「任意服務端」的自動刷新端點:http://localhost:8888/actuator/bus-refresh/order-service:** 再次訪問結果如下:

至此 Bus 消息總線所有的知識點就講解結束了。

EOF

本文作者:哈嘍沃德先生
本文鏈接:https://www.cnblogs.com/mrhelloworld/p/bus.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章