書接上回:

SpringCloud專題之一:Eureka

Spring Cloud專題之二:OpenFeign

Spring Cloud專題之三:Hystrix

Spring Cloud 專題之四:Zuul閘道器

Spring Cloud專題之五:config

在上一篇文章中,我們說到了如果config server的配置檔案發生了修改,config client可以通過執行/actutor/refresh來實現熱重新整理。但是這也做的弊端也很明顯,如果有幾十上百個config client,需要一個服務一個服務地傳送請求,可能會被運維兄弟打死。。。。。。那麼在微服務專案中,Spring Cloud Bus這個必備元件就不得不出場了。

Spring Cloud Bus,俗稱訊息匯流排,通過使用輕量級的訊息代理來構建一個公共地訊息主題讓系統中所有的微服務例項都連線上來,在總線上的各個例項都可以方便地廣播一些需要讓其他連線在該主題上地例項都知道訊息,例如配置資訊的變更或者其他一些管理操作等。

訊息代理

訊息代理是一種訊息驗證、傳熟、路由的架構模式,他在應用程式之間起到通訊排程並最小化應用之間的依賴的作用,是的應用程式可以高效的解耦通訊過程。他的核心是一個訊息的路由程式,用來實現接收和分發訊息,並根據設定好的訊息處理流來轉發給正確的應用。

常用的使用場景:

  • 將訊息路由到一個或多個目的地
  • 訊息轉化為其他的表現方式
  • 執行訊息的聚集、訊息的分解,並將結果傳送到他們的目的地,然後重新組合響應返回給訊息使用者
  • 呼叫web服務來檢索資料
  • 響應事件或錯誤
  • 使用釋出-訂閱模式來提供內容或基於主題的訊息路由

目前支援Spring Cloud Bus的訊息中介軟體只有這兩個:RabbitMQ和Kafka。

RabbitMQ實現訊息匯流排

關於RabbitMQ,歡迎檢視我之間的部落格:訊息佇列之RabbitMQ

訊息匯流排bus是基於Actuator對外提供熱重新整理服務。

1.擴充套件之前的config-client專案

因為我這邊用config-client做測試,引入spring-cloud-starter-bus-amqp會下圖這個錯,

所以在引入bus-amqp的依賴的時候,改了spring boot的版本,我其他spring cloud元件所用的spring boot版本都是2.3.10.RELEASE,在引入bus元件後spring cloud的版本修改為2.1.4.RELEASE,spring cloud的版本修改為Greenwich.SR1。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.charon</groupId>
<artifactId>config-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>config-client</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency> <!-- 新增spring cloud bus的依賴 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

2.配置檔案的資訊

spring.application.name=config-client
server.port=9011 spring.cloud.compatibility-verifier.enabled=false # 需要配置spring cloud config server位置和要載入的相關引數
# spring cloud config server的連線地址
spring.cloud.config.uri=http://localhost:8888
# 要載入的配置檔案主體命名
spring.cloud.config.name=config
# 要載入的配置檔案的profile,預設為default
spring.cloud.config.profile=default
# 要載入的配置檔案所在的分支命名,預設為null,相當於master
spring.cloud.config.label=master eureka.client.serviceUrl.defaultZone=http://eureka-server1:9001/eureka/ # 配置rabbitMQ的相關資訊
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest # 設定應用是否連線到訊息總線上
spring.cloud.bus.enabled=true
management.endpoints.web.exposure.include=info,health,refresh,bus-refresh

3.打包成jar,然後使用java -jar命令啟動兩個服務,9011,9012

如下圖所示,訪問9011和9012得到的配置資訊如下:

訪問rabbitmq的頁面,可以看到預設建立了一個exchange:springCloudBus

4.修改git上的值,並使用postman傳送post請求。

5.檢視

如此這樣,只需要傳送一次bus-refresh請求,兩個config client服務的配置都發生了修改。

詳細說明

在本示例中,我使用的架構圖如下所示:

其中包含了Git倉庫,config server以及幾個config client服務,config client服務都引入了Spring Cloud Bus,所以他們都連線到了RabbitMQ的訊息總線上。

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

此時,若我們需要修改“Service A”的屬性。首先,通過Git管理工具去倉庫中修改對應的屬性值,但是這個修改並不會觸發“Service A”例項的屬性更新。我們向“Service A”的例項3傳送POST請求,訪問/bus/refresh(本示例中為/actuator/bus-refresh)介面。此時,“Service A”的例項3就會將重新整理請求傳送到訊息匯流排中,該訊息事件會被“Service A”的例項1和例項2從匯流排中獲取到,並重新從Config Server中獲取它們的配置資訊,從而實現配置資訊的動態更新。

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

RabbitMQ使用的為topic交換器,配合#路由鍵做廣播訊息處理。

指定重新整理範圍

Spring Cloud Bus也支援在bus-refresh介面中提供一個destination的引數,用來定位具體要重新整理的服務。

將git殘酷中的age值從100改為101,在postman中指定重新整理9011的服務

這樣就是有9011服務的值修改了,而9012服務的值並沒有修改。

參考文章:

翟永超老師的《Spring Cloud微服務實戰》

https://forezp.blog.csdn.net/article/details/70148235