簡介
在上篇文章《微服務(wù)之配置中心》中寫到,客戶端可從服務(wù)端獲取配置信息,當(dāng)Git倉庫中的配置文件修改后,為了讓客戶端獲取最新的配置信息,可以通過執(zhí)行refresh操作進(jìn)行手動刷新。但是這樣有問題,當(dāng)客戶端很多時(隨之系統(tǒng)的不斷擴(kuò)大),如果需要每個客戶端都執(zhí)行一遍,那就蛋疼了,顯然這種方案就不適合了。Spring Cloud作為微服務(wù)架構(gòu)的一個綜合解決方案,也提供了對應(yīng)的解決方案Spring Cloud Bus,即消息總線。
這里要理解一個概念,消息總線。簡單理解就是一個消息中心,眾多微服務(wù)實例可以連接到總線上,實例可以往消息中心發(fā)送或接收信息(通過監(jiān)聽)。比如:實例A發(fā)送一條消息到總線上,總線上的實例B可以接收到信息(實例B訂閱了實例A),這樣的話,消息總線就充當(dāng)一個中間者的角色,使得實例A和實例B解偶了,很方便。
消息總線(Spring Cloud Bus)
原理
Spring Cloud Bus通過建立多個應(yīng)用之間的通信頻道,管理和傳播應(yīng)用間的消息,從技術(shù)角度來說,應(yīng)用了AMQP消息代理作為通道,通過MQ的廣播機(jī)制實現(xiàn)消息的發(fā)送和接收。以其典型應(yīng)用——配置中心客戶端刷新為例,說明下工作流程:
(1)修改配置文件,觸發(fā)webhook向clientA發(fā)送bus/refresh;
(2)clientA重新從配置中心獲取新的配置信息,同時發(fā)送消息到Spring Cloud Bus;
(3)Spring Cloud Bus收到消息,同時通知clientB、clientC(訂閱配置更新事件);
(4)clientB、clientC收到通知,重新請求配置中心,獲取新的配置信息。
這樣,三個客戶端均得到最新的配置。
消息代理
這個過程中,作為通道的AMQP消息代理很重要。AMQP(高級消息隊列協(xié)議,是一個標(biāo)準(zhǔn))是一個網(wǎng)絡(luò)協(xié)議,從扮演角色來說,消息代理從生產(chǎn)者(producers)那兒接收消息,并根據(jù)既定的路由規(guī)則把接收到的消息發(fā)送給處理消息的消費者(consumers),這個過程中的發(fā)布者,消費者,消息代理可以存在于不同的設(shè)備上,下面簡單介紹下工作流程(其實跟上面的類似):
消息(message)被發(fā)布者(publisher)發(fā)送給交換機(jī)(exchange),交換機(jī)常常被比喻成郵局或者郵箱。然后交換機(jī)將收到的消息根據(jù)路由規(guī)則分發(fā)給綁定的隊列(queue)。最后AMQP代理會將消息投遞給訂閱了此隊列的消費者,或者消費者按照需求自行獲取。
? ? ? AMQP作為一個標(biāo)準(zhǔn)協(xié)議,主要實現(xiàn)方案有RabbitMQ、ActiveMQ、Qpid等。這里我主要以RabbitMQ為例進(jìn)行說明,它是一個優(yōu)秀的微服務(wù)架構(gòu)消息中間件,與Spring Cloud Bus能夠很好的結(jié)合使用。
下圖顯示了RabbitMQ的Web管理首頁:
(1)Broker:消息隊列服務(wù)器,即負(fù)責(zé)接收生產(chǎn)者消息,發(fā)送至消費者的;
(2)Connections:連接,即發(fā)送者、消息接收者、消費者之間的物理連接;
(3)Channel:通道,連接生產(chǎn)者、消費者的邏輯結(jié)構(gòu)。一個Connection可以對應(yīng)多個Channel;
(4)Exchange:消息交換機(jī),消息第一個到達(dá)的地方,可以指定路由規(guī)則,決定消息分發(fā)到不同的消息隊列中去;
(5)Queue:消息隊列,消息經(jīng)Exchange路由轉(zhuǎn)發(fā)至此,進(jìn)入邏輯等待狀態(tài)(等待消費,即客戶端獲?。?/p>
(6)Binding:綁定,把Exchange和Queue按照路由規(guī)則進(jìn)行綁定,即決定Exchange接收消息后,需要發(fā)送到哪些Queue中:
消息發(fā)送-接收原理圖
配置步驟
Config Server服務(wù)端
(1)在Config Server添加RabbitMQ依賴,非常簡單:
(2)修改配置文件,添加RabbitMQ的配置信息:
(3)啟動類加注解:
Config Client客戶端
(1)在Config Client添加RabbitMQ依賴,非常簡單:
(2)修改配置文件,添加RabbitMQ的配置信息:
Eureka Server注冊中心
省略。
測試
(1)啟動Eureka Server注冊中心、ConfigServer服務(wù)端、Config Client客戶端(開啟兩個實例),如圖:
(2)客戶端獲取配置文件的值,如圖:



(3)修改配置文件值,改為apps.caac.net/demo,如圖:

(4)通過curl執(zhí)行刷新操作(配置服務(wù)端執(zhí)行/bus/refresh),如圖:

(5)客戶端重新獲取配置文件的值,可知已獲取最新配置信息,如圖:


(6)至此完成配置自動刷新,當(dāng)部署正式環(huán)境時,可以在配置文件修改時自動執(zhí)行一個操作:curl -X POST http://localhost:8889/bus/refresh,在碼云后臺可以進(jìn)行設(shè)置(這里測試環(huán)境,設(shè)置不了,必須是公網(wǎng)地址),如圖:
局部刷新
有時我們只想刷新部分微服務(wù)的配置,此時可通過/bus/refresh端點的destination參數(shù)來定位要刷新的應(yīng)用程序。
刷新指定實例(某一服務(wù))
執(zhí)行:/bus/refresh?destination=customers:9000,
其中,customers:9000指的是各個微服務(wù)的ApplicationContext ID(默認(rèn)為:${spring.application.name}:${server.port})。
刷新全部實例(某一服務(wù))
執(zhí)行:/bus/refresh?destination=customers:**,這樣就可以觸發(fā)customers微服務(wù)所有實例的配置刷新。

注意:這里的${spring.application.name}區(qū)分大小寫。