消息代理中間件構(gòu)建一個(gè)共用的消息主題讓所有微服務(wù)實(shí)例訂閱霉颠,當(dāng)該消息主題產(chǎn)生消息時(shí)會(huì)被所有微服務(wù)實(shí)例監(jiān)聽(tīng)和消費(fèi)。
消息代理又是什么荆虱?消息代理是一個(gè)消息驗(yàn)證蒿偎、傳輸朽们、路由的架構(gòu)模式,主要用來(lái)實(shí)現(xiàn)接收和分發(fā)消息诉位,并根據(jù)設(shè)定好的消息處理流來(lái)轉(zhuǎn)發(fā)給正確的應(yīng)用骑脱。它在微服務(wù)之間起到通信調(diào)度作用,減少了服務(wù)之間的依賴(lài)苍糠。
什么是 Spring Cloud Bus
Spring Cloud Bus 是 Spring Cloud 體系內(nèi)的消息總線叁丧,用來(lái)連接分布式系統(tǒng)的所有節(jié)點(diǎn)。
Spring Cloud Bus 將分布式的節(jié)點(diǎn)用輕量的消息代理(RibbitMQ岳瞭、Kafka)連接起來(lái)拥娄。可以通過(guò)消息代理廣播配置文件的更改瞳筏,或服務(wù)之間的通訊稚瘾,也可以用于監(jiān)控。解決了微服務(wù)數(shù)據(jù)變更乏矾,及時(shí)同步的問(wèn)題孟抗。
什么時(shí)候使用 Spring Cloud Bus
微服務(wù)一般都采用集群方式部署,而且在高并發(fā)下經(jīng)常需要對(duì)服務(wù)進(jìn)行擴(kuò)容钻心、縮容、上線铅协、下線的操作捷沸。比如我們需要更新配置,又或者需要同時(shí)失效所有服務(wù)器上的某個(gè)緩存狐史,需要向所有相關(guān)的服務(wù)器發(fā)送命令痒给,此時(shí)就可以選擇使用 Spring Cloud Bus 了。
總的來(lái)說(shuō)骏全,就是在我們需要把一個(gè)操作散發(fā)到所有后端相關(guān)服務(wù)器的時(shí)候苍柏,就可以選擇使用 Spring Cloud Bus 了。
接下來(lái)我們通過(guò) Spring Cloud Bus 實(shí)現(xiàn)微服務(wù)架構(gòu)的配置刷新姜贡。
環(huán)境準(zhǔn)備
RibbitMQ v3.8.2 地址:192.168.10.101
bus-demo 聚合工程 SpringBoot 2.2.4.RELEASE试吁、Spring Cloud Hoxton.SR1。
eureka-server:注冊(cè)中心
eureka-server02:注冊(cè)中心
config-server:配置中心服務(wù)端
config-server02:配置中心服務(wù)端
order-service:訂單服務(wù)(配置中心客戶(hù)端)
order-service02:訂單服務(wù)(配置中心客戶(hù)端)
配置文件 order-service-prod.yml
spring:
? application:
? ? name: order-service # 應(yīng)用名稱(chēng)
# 配置 Eureka Server 注冊(cè)中心
eureka:
? instance:
? ? prefer-ip-address: true? ? ? # 是否使用 ip 地址注冊(cè)
? ? instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port
? client:
? ? service-url:? ? ? ? ? ? ? ? ? # 設(shè)置服務(wù)注冊(cè)中心地址
? ? ? defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
# 自定義配置
name: order-service-prod
password: root
Spring Cloud Bus 實(shí)現(xiàn)配置刷新
客戶(hù)端發(fā)起通知
消息總線(Bus)的典型應(yīng)用場(chǎng)景就是配置中心客戶(hù)端刷新楼咳。
我們?cè)趯W(xué)習(xí) Spring Cloud Config 配置中心時(shí)給大家講了基于 Actuator 的配置刷新熄捍,當(dāng)時(shí)的案例只有一個(gè) Config Client,我們可以使用 Webhook母怜,設(shè)置手動(dòng)刷新都不算太費(fèi)事余耽,但是如果客戶(hù)端比較多的情況下,一個(gè)一個(gè)去手動(dòng)刷新未免有點(diǎn)復(fù)雜苹熏,這種方案就不太適合了碟贾。使用 Spring Cloud Bus 可以完美解決這一問(wèn)題币喧。
借助 Spring Cloud Bus 的廣播功能,讓 Config Client 都訂閱配置更新事件袱耽,當(dāng)配置更新時(shí)粱锐,觸發(fā)其中一個(gè)端的更新事件,Spring Cloud Bus 就把此事件廣播到其他訂閱客戶(hù)端扛邑,以此來(lái)達(dá)到批量更新怜浅。
Webhook 監(jiān)聽(tīng)被觸發(fā),給 ConfigClient A 發(fā)送 bus-refresh 請(qǐng)求刷新配置
ConfigClient A 讀取 ConfigServer 中的配置蔬崩,并且發(fā)送消息給 Bus
Bus 接收消息后廣播通知其他 ConfigClient
其他 ConfigClient 收到消息重新讀取最新配置
添加依賴(lài)
Config Client 添加 spring cloud starter bus amqp 依賴(lài)恶座。
<!-- spring cloud starter bus amqp 依賴(lài) -->
<dependency>
? ? <groupId>org.springframework.cloud</groupId>
? ? <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
配置文件
配置文件需要配置 消息隊(duì)列 和 bus-refresh 自動(dòng)刷新端點(diǎn)。/actuator/bus-refresh 端點(diǎn)會(huì)清除 @RefreshScope 緩存重新綁定屬性沥阳。
Config Client 的 bootstrap.yml 核心配置跨琳。
spring:
? cloud:
? ? config:
? ? ? name: order-service # 配置文件名稱(chēng),對(duì)應(yīng) git 倉(cāng)庫(kù)中配置文件前半部分
? ? ? label: master # git 分支
? ? ? profile: prod # 指定環(huán)境
? ? ? discovery:
? ? ? ? enabled: true # 開(kāi)啟
? ? ? ? service-id: config-server # 指定配置中心服務(wù)端的 service-id
? # 消息隊(duì)列
? rabbitmq:
? ? host: 192.168.10.106
# 度量指標(biāo)監(jiān)控與健康檢查
management:
? endpoints:
? ? web:
? ? ? base-path: /actuator? ? # 訪問(wèn)端點(diǎn)根路徑桐罕,默認(rèn)為 /actuator
? ? ? exposure:
? ? ? ? include: bus-refresh? # 需要開(kāi)啟的端點(diǎn)
? ? ? ? #exclude:? ? ? ? ? ? # 不需要開(kāi)啟的端點(diǎn)
測(cè)試
查看端點(diǎn)
可以看到已經(jīng)開(kāi)啟了 bus-refresh 自動(dòng)刷新端點(diǎn)脉让。
修改 Git 倉(cāng)庫(kù)配置
修改 Git 倉(cāng)庫(kù)配置信息如下:
# 自定義配置
name: order-service-prod-1.0
自動(dòng)刷新
刷新頁(yè)面發(fā)現(xiàn)結(jié)果并未改變,沒(méi)事正常功炮。
通過(guò) Post 方式調(diào)用任意客戶(hù)端的自動(dòng)刷新端點(diǎn):再次訪問(wèn)結(jié)果如下:
查看隊(duì)列
再來(lái)觀察一下消息隊(duì)列的 UI 界面溅潜,發(fā)現(xiàn)多了一個(gè) springCloudBus 的交換機(jī)。
該交換機(jī)下綁定了兩個(gè)隊(duì)列對(duì)應(yīng)我們的兩個(gè) Config Client薪伏。
客戶(hù)端發(fā)起通知缺陷
打破了微服務(wù)的職責(zé)單一性滚澜。微服務(wù)本身是業(yè)務(wù)模塊,它本不應(yīng)該承擔(dān)配置刷新的職責(zé)嫁怀。
破壞了微服務(wù)各節(jié)點(diǎn)的對(duì)等性设捐。
存在一定的局限性。例如塘淑,微服務(wù)在遷移時(shí)萝招,它的網(wǎng)絡(luò)地址常常會(huì)發(fā)生變化,此時(shí)如果想要做到自動(dòng)刷新存捺,就不得不修改Webhook 的配置槐沼。
服務(wù)端發(fā)起通知
為了解決客戶(hù)端發(fā)起通知缺陷,我們改用服務(wù)端發(fā)起通知召噩。
Webhook監(jiān)聽(tīng)被觸發(fā)母赵,給 ConfigServer 發(fā)送 bus-refresh 請(qǐng)求刷新配置
ConfigServer 發(fā)送消息給 Bus
Bus 接收消息后廣播通知所有 ConfigClient
歌 ConfigClient 收到消息重新讀取最新配置
添加依賴(lài)
Config Server 添加 spring cloud starter bus amqp 依賴(lài)。
<!-- spring cloud starter bus amqp 依賴(lài) -->
<dependency>
? ? <groupId>org.springframework.cloud</groupId>
? ? <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
配置文件
配置文件需要配置 消息隊(duì)列 和 bus-refresh 自動(dòng)刷新端點(diǎn)具滴。/actuator/bus-refresh 端點(diǎn)會(huì)清除 @RefreshScope 緩存重新綁定屬性凹嘲。
Config Server 的 application.yml 核心配置。
spring:
? application:
? ? name: config-server # 應(yīng)用名稱(chēng)
? cloud:
? ? config:
? ? ? server:
? ? ? ? git:
? ? ? ? ? uri: https://github.com/imrhelloworld/config-repo # 配置文件所在倉(cāng)庫(kù)地址
? ? ? ? ? #username:? ? ? ? ? ? # Github 等產(chǎn)品的登錄賬號(hào)
? ? ? ? ? #password:? ? ? ? ? ? # Github 等產(chǎn)品的登錄密碼
? ? ? ? ? #default-label: master # 配置文件分支
? ? ? ? ? #search-paths:? ? ? ? # 配置文件所在根目錄
? # 消息隊(duì)列
? rabbitmq:
? ? host: 192.168.10.106
# 配置 Eureka Server 注冊(cè)中心
eureka:
? instance:
? ? prefer-ip-address: true? ? ? # 是否使用 ip 地址注冊(cè)
? ? instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port
? client:
? ? service-url:? ? ? ? ? ? ? ? ? # 設(shè)置服務(wù)注冊(cè)中心地址
? ? ? defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
# 度量指標(biāo)監(jiān)控與健康檢查
management:
? endpoints:
? ? web:
? ? ? base-path: /actuator? ? # 訪問(wèn)端點(diǎn)根路徑构韵,默認(rèn)為 /actuator
? ? ? exposure:
? ? ? ? include: bus-refresh? # 需要開(kāi)啟的端點(diǎn)
? ? ? ? #exclude:? ? ? ? ? ? # 不需要開(kāi)啟的端點(diǎn)