Spring Cloud構建微服務架構(七)消息總線

先回顧一下,在之前的Spring Cloud Config的介紹中,我們還留了一個懸念:如何實現對配置信息的實時更新。雖然,我們已經能夠通過/refresh接口和Git倉庫的Web Hook來實現Git倉庫中的內容修改觸發應用程序的屬性更新。但是,若所有觸發操作均需要我們手工去維護Web Hook中的應用位置的話,這隨著系統的不斷擴張,會變的越來越難以維護,而消息代理中間件是解決該問題最為合適的方案。是否還記得我們在介紹消息代理中的特點時有提到過這樣一個功能:消息代理中間件可以將消息路由到一個或多個目的地。利用這個功能,我們就能完美的解決該問題,下面我們來說說Spring Cloud Bus中的具體實現方案。

《Spring Boot中使用RabbitMQ》一文中,我們已經介紹了關于消息代理、AMQP協議以及RabbitMQ的基礎知識和使用方法。下面我們開始具體介紹Spring Cloud Bus的配置,并以一個Spring Cloud Bus與Spring Cloud Config結合的例子來實現配置內容的實時更新。

RabbitMQ實現

下面我們來具體動手嘗試整個配置過程:

  • 準備工作:這里我們不做新的應用,但需要用到上一章中,我們已經實現的關于Spring Cloud Config的幾個工程,若讀者對其還不了解,建議先閱讀第4章的內容。
    • config-repo:定義在Git倉庫中的一個目錄,其中存儲了應用名為didispace的多環境配置文件,配置文件中有一個from參數。
    • config-server-eureka:配置了Git倉庫,并注冊到了Eureka的服務端。
    • config-client-eureka:通過Eureka發現Config Server的客戶端,應用名為didispace,用來訪問配置服務器以獲取配置信息。該應用中提供了一個/from接口,它會獲取config-repo/didispace-dev.properties中的from屬性返回。
  • 擴展config-client-eureka應用
    • 修改pom.xml增加spring-cloud-starter-bus-amqp模塊(注意spring-boot-starter-actuator模塊也是必須的)。
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
  • 在配置文件中增加關于RabbitMQ的連接和用戶信息
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=springcloud
spring.rabbitmq.password=123456
  • 啟動config-server-eureka,再啟動兩個config-client-eureka(分別在不同的端口上,比如7002、7003),我們可以在config-client-eureka中的控制臺中看到如下內容,在啟動時候,客戶端程序多了一個/bus/refresh請求。
o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/bus/refresh],methods=[POST]}" onto public void org.springframework.cloud.bus.endpoint.RefreshBusEndpoint.refresh(java.lang.String)
  • 先訪問兩個config-client-eureka的/from請求,會返回當前config-repo/didispace-dev.properties中的from屬性。
  • 接著,我們修改config-repo/didispace-dev.properties中的from屬性值,并發送POST請求到其中的一個/bus/refresh
  • 最后,我們再分別訪問啟動的兩個config-client-eureka的/from請求,此時這兩個請求都會返回最新的config-repo/didispace-dev.properties中的from屬性。

到這里,我們已經能夠通過Spring Cloud Bus來實時更新總線上的屬性配置了。

原理分析

我們通過使用Spring Cloud Bus與Spring Cloud Config的整合,并以RabbitMQ作為消息代理,實現了應用配置的動態更新。

整個方案的架構如上圖所示,其中包含了Git倉庫、Config Server、以及微服務“Service A”的三個實例,這三個實例中都引入了Spring Cloud Bus,所以他們都連接到了RabbitMQ的消息總線上。

當我們將系統啟動起來之后,“Service A”的三個實例會請求Config Server以獲取配置信息,Config Server根據應用配置的規則從Git倉庫中獲取配置信息并返回。

此時,若我們需要修改“Service A”的屬性。首先,通過Git管理工具去倉庫中修改對應的屬性值,但是這個修改并不會觸發“Service A”實例的屬性更新。我們向“Service A”的實例3發送POST請求,訪問/bus/refresh接口。此時,“Service A”的實例3就會將刷新請求發送到消息總線中,該消息事件會被“Service A”的實例1和實例2從總線中獲取到,并重新從Config Server中獲取他們的配置信息,從而實現配置信息的動態更新。

而從Git倉庫中配置的修改到發起/bus/refresh的POST請求這一步可以通過Git倉庫的Web Hook來自動觸發。由于所有連接到消息總線上的應用都會接受到更新請求,所以在Web Hook中就不需要維護所有節點內容來進行更新,從而解決了通過Web Hook來逐個進行刷新的問題。

指定刷新范圍

上面的例子中,我們通過向服務實例請求Spring Cloud Bus的/bus/refresh接口,從而觸發總線上其他服務實例的/refresh。但是有些特殊場景下(比如:灰度發布),我們希望可以刷新微服務中某個具體實例的配置。

Spring Cloud Bus對這種場景也有很好的支持:/bus/refresh接口還提供了destination參數,用來定位具體要刷新的應用程序。比如,我們可以請求/bus/refresh?destination=customers:9000,此時總線上的各應用實例會根據destination屬性的值來判斷是否為自己的實例名,若符合才進行配置刷新,若不符合就忽略該消息。

destination參數除了可以定位具體的實例之外,還可以用來定位具體的服務。定位服務的原理是通過使用Spring的PathMatecher(路徑匹配)來實現,比如:/bus/refresh?destination=customers:**,該請求會觸發customers服務的所有實例進行刷新。

架構優化

既然Spring Cloud Bus的/bus/refresh接口提供了針對服務和實例進行配置更新的參數,那么我們的架構也相應的可以做出一些調整。在之前的架構中,服務的配置更新需要通過向具體服務中的某個實例發送請求,再觸發對整個服務集群的配置更新。雖然能實現功能,但是這樣的結果是,我們指定的應用實例就會不同于集群中的其他應用實例,這樣會增加集群內部的復雜度,不利于將來的運維工作,比如:我們需要對服務實例進行遷移,那么我們不得不修改Web Hook中的配置等。所以我們要盡可能的讓服務集群中的各個節點是對等的。

因此,我們將之前的架構做了一些調整,如下圖所示:

我們主要做了這些改動:

  1. 在Config Server中也引入Spring Cloud Bus,將配置服務端也加入到消息總線中來。
  2. /bus/refresh請求不在發送到具體服務實例上,而是發送給Config Server,并通過destination參數來指定需要更新配置的服務或實例。

通過上面的改動,我們的服務實例就不需要再承擔觸發配置更新的職責。同時,對于Git的觸發等配置都只需要針對Config Server即可,從而簡化了集群上的一些維護工作。

本文完整示例:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,732評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,214評論 3 426
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,781評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,588評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,315評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,699評論 1 327
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,698評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,882評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,441評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,189評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,388評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,933評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,613評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,023評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,310評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,112評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,334評論 2 377

推薦閱讀更多精彩內容