SpringCloud系列教程 | 第八篇:Spring Cloud Bus 消息匯流排 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如無特殊說明,本系列教程全採用以上版本 前面兩篇文章我們聊了Spring Cloud Config配置中心 ...
SpringCloud系列教程 | 第八篇:Spring Cloud Bus 消息匯流排
Springboot: 2.1.6.RELEASE
SpringCloud: Greenwich.SR1
如無特殊說明,本系列教程全採用以上版本
前面兩篇文章我們聊了Spring Cloud Config配置中心,當我們在更新github上面的配置以後,如果想要獲取到最新的配置,需要手動刷新或者利用webhook的機制每次提交代碼發送請求來刷新客戶端,客戶端越來越多的時候,需要每個客戶端都執行一遍,這種方案就不太適合了。使用Spring Cloud Bus(國人很形象的翻譯為消息匯流排,我比較喜歡叫消息公車)可以完美解決這一問題。
1. Spring Cloud Bus
Spring cloud bus通過輕量消息代理連接各個分佈的節點。這會用在廣播狀態的變化(例如配置變化)或者其他的消息指令。Spring bus的一個核心思想是通過分散式的啟動器對spring boot應用進行擴展,也可以用來建立一個多個應用之間的通信頻道。目前唯一實現的方式是用AMQP消息代理作為通道,同樣特性的設置(有些取決於通道的設置)在更多通道的文檔中。
大家可以將它理解為管理和傳播所有分散式項目中的消息既可,其實本質是利用了MQ的廣播機制在分散式的系統中傳播消息,目前常用的有Kafka和RabbitMQ。利用bus的機制可以做很多的事情,其中配置中心客戶端刷新就是典型的應用場景之一,我們用一張圖來描述bus在配置中心使用的機制。
根據此圖我們可以看出利用Spring Cloud Bus做配置更新的步驟:
- 提交代碼觸發post給客戶端A發送bus/refresh
- 客戶端A接收到請求從Server端更新配置並且發送給Spring Cloud Bus
- Spring Cloud bus接到消息並通知給其它客戶端
- 其它客戶端接收到通知,請求Server端獲取最新配置
- 全部客戶端均獲取到最新的配置
2. 項目示例
我們使用上一篇文章中的config-server和config-client來進行改造,mq使用rabbitmq來做示例。
2.1 客戶端config-client
2.1.1 添加依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
需要多引入spring-cloud-starter-bus-amqp包,增加對消息匯流排的支持
2.1.2 配置文件 bootstrap.properties
spring.application.name=spring-cloud-config-client
server.port=8081
spring.cloud.config.name=springcloud-config
spring.cloud.config.profile=dev
spring.cloud.config.label=master
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=spring-cloud-config-server
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
management.endpoints.web.exposure.include=*
## 開啟消息跟蹤
spring.cloud.bus.trace.enabled=true
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=
spring.rabbitmq.password=
配置文件需要增加RebbitMq的相關配置,這樣客戶端代碼就改造完成了。
2.1.3 測試
依次啟動eureka,config-serve,config-client。
修改config-client啟動配置,同時在8081和8082埠啟動服務。
啟動完成後,瀏覽器分別訪問連接:http://localhost:8081/hello, http://localhost:8082/hello, 可以發現頁面顯示的內容都是:hello dev update1,說明客戶端都已經讀取到了server端的內容。
現在我們更新github上的配置文件,將配置內容改為hello dev update,先訪問一下http://localhost:8081/hello,可以看到頁面依然顯示為:hello dev update1。
我們對埠為8081的服務發送一個/actuator/bus-refresh的POST請求,在win10下使用下麵命令來模擬webhook。
curl -X POST http://localhost:8081/actuator/bus-refresh
註意: 在springboot2.x的版本中刷新路徑為:/actuator/bus-refresh,在springboot1.5.x的版本中刷新路徑為:/bus/refresh。
執行完成後,我們先訪問http://localhost:8082/hello,可以看到頁面列印內容已經變為:hello dev update,這樣說明,我們8081埠的服務已經把更新後的信息通過rabbitmq推送給了8082埠的服務,這樣我們就實現了圖一中的示例。
2.2 改進版
上面的流程中,雖然我們做到了利用一個消息匯流排觸發刷新,而刷新所有客戶端配置的目的,但是這種方式並不合適,如下:
- 打破了微服務的職責單一性。微服務本身是業務模塊,它本不應該承擔配置刷新的職責。
- 破壞了微服務各節點的對等性。
- 如果客戶端ip有變化,這時我們就需要修改WebHook的配置。
我們可以將上面的流程改進一下:
這時Spring Cloud Bus做配置更新步驟如下:
- 提交代碼觸發post給Server端發送bus/refresh
- Server端接收到請求併發送給Spring Cloud Bus
- Spring Cloud bus接到消息並通知給其它客戶端
- 其它客戶端接收到通知,請求Server端獲取最新配置
- 全部客戶端均獲取到最新的配置
這樣的話我們在server端的代碼做一些改動,來支持/actuator/bus-refresh
和上面的client端的改動基本一致
2.2.1 添加依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
需要多引入spring-cloud-starter-bus-amqp包,增加對消息匯流排的支持
2.2.2 配置文件application.yml
server:
port: 8080
spring:
application:
name: spring-cloud-config-server
cloud:
config:
server:
git:
uri: https://github.com/meteor1993/SpringCloudLearning
search-paths: chapter6/springcloud-config
username:
password:
rabbitmq:
host: 217.0.0。1
port: 5672
username:
password:
management:
endpoints:
web:
exposure:
include: "*"
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
配置文件需要增加RebbitMq的相關配置,actuator開啟所有訪問。
2.2.3 測試
依次啟動eureka,config-serve,config-client。
修改config-client啟動配置,同時在8081和8082埠啟動服務。
按照上面的測試方式,訪問兩個客戶端測試均可以正確返回信息。同樣修改配置文件,將值改為:hello im dev update並提交到倉庫中。在win10下使用下麵命令來模擬webhook。
curl -X POST http://localhost:8081/actuator/bus-refresh
執行完成後,依次訪問兩個客戶端,返回:hello im dev update。說明三個客戶端均已經拿到了最新配置文件的信息,這樣我們就實現了上圖中的示例。
參考:http://www.ityouknow.com/springcloud/2017/05/26/springcloud-config-eureka-bus.html