1. 程式人生 > >Spring Cloud 系列之 Bus 訊息匯流排

Spring Cloud 系列之 Bus 訊息匯流排

什麼是訊息匯流排

訊息代理中介軟體構建一個共用的訊息主題讓所有微服務例項訂閱,當該訊息主題產生訊息時會被所有微服務例項監聽和消費。

訊息代理又是什麼?訊息代理是一個訊息驗證、傳輸、路由的架構模式,主要用來實現接收和分發訊息,並根據設定好的訊息處理流來轉發給正確的應用。它在微服務之間起到通訊排程作用,減少了服務之間的依賴。

什麼是 Spring Cloud Bus

Spring Cloud Bus 是 Spring Cloud 體系內的訊息匯流排,用來連線分散式系統的所有節點。

Spring Cloud Bus 將分散式的節點用輕量的訊息代理(RibbitMQ、Kafka)連線起來。可以通過訊息代理廣播配置檔案的更改,或服務之間的通訊,也可以用於監控。解決了微服務資料變更,及時同步的問題。

官方文件:https://cloud.spring.io/spring-cloud-static/spring-cloud-bus/2.2.1.RELEASE/reference/html/

什麼時候使用 Spring Cloud Bus

微服務一般都採用叢集方式部署,而且在高併發下經常需要對服務進行擴容、縮容、上線、下線的操作。比如我們需要更新配置,又或者需要同時失效所有伺服器上的某個快取,需要向所有相關的伺服器傳送命令,此時就可以選擇使用 Spring Cloud Bus 了。

總的來說,就是在我們需要把一個操作散發到所有後端相關伺服器的時候,就可以選擇使用 Spring Cloud Bus 了。

接下來我們通過 Spring Cloud Bus 實現微服務架構的配置重新整理。

環境準備

RibbitMQ v3.8.2 地址:192.168.10.101

bus-demo 聚合工程。SpringBoot 2.2.4.RELEASESpring Cloud Hoxton.SR1

  • eureka-server:註冊中心
  • eureka-server02:註冊中心
  • config-server:配置中心服務端
  • config-server02:配置中心服務端
  • order-service:訂單服務(配置中心客戶端)
  • order-service02:訂單服務(配置中心客戶端)

配置檔案 order-service-prod.yml

spring:
  application:
    name: order-service # 應用名稱

# 配置 Eureka Server 註冊中心
eureka:
  instance:
    prefer-ip-address: true       # 是否使用 ip 地址註冊
    instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port
  client:
    service-url:                  # 設定服務註冊中心地址
      defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/

# 自定義配置
name: order-service-prod
password: root

Spring Cloud Bus 實現配置重新整理

客戶端發起通知

點選連結觀看:客戶端發起通知視訊(獲取更多請關注公眾號「哈嘍沃德先生」)

訊息匯流排(Bus)的典型應用場景就是配置中心客戶端重新整理。

我們在學習 Spring Cloud Config 配置中心時給大家講了基於 Actuator 的配置重新整理,當時的案例只有一個 Config Client,我們可以使用 Webhook,設定手動重新整理都不算太費事,但是如果客戶端比較多的情況下,一個一個去手動重新整理未免有點複雜,這種方案就不太適合了。使用 Spring Cloud Bus 可以完美解決這一問題。

藉助 Spring Cloud Bus 的廣播功能,讓 Config Client 都訂閱配置更新事件,當配置更新時,觸發其中一個端的更新事件,Spring Cloud Bus 就把此事件廣播到其他訂閱客戶端,以此來達到批量更新。

  1. Webhook 監聽被觸發,給 ConfigClient A 傳送 bus-refresh 請求重新整理配置
  2. ConfigClient A 讀取 ConfigServer 中的配置,並且傳送訊息給 Bus
  3. Bus 接收訊息後廣播通知其他 ConfigClient
  4. 其他 ConfigClient 收到訊息重新讀取最新配置

新增依賴

Config Client 新增 spring cloud starter bus amqp 依賴。

<!-- spring cloud starter bus amqp 依賴 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

配置檔案

配置檔案需要配置 訊息佇列bus-refresh 自動重新整理端點。/actuator/bus-refresh 端點會清除 @RefreshScope 快取重新繫結屬性。

Config Client 的 bootstrap.yml 核心配置。

spring:
  cloud:
    config:
      name: order-service # 配置檔名稱,對應 git 倉庫中配置檔案前半部分
      label: master # git 分支
      profile: prod # 指定環境
      discovery:
        enabled: true # 開啟
        service-id: config-server # 指定配置中心服務端的 service-id
  # 訊息佇列
  rabbitmq:
    host: 192.168.10.101
    port: 5672
    username: guest
    password: guest
    virtual-host: /

# 度量指標監控與健康檢查
management:
  endpoints:
    web:
      base-path: /actuator    # 訪問端點根路徑,預設為 /actuator
      exposure:
        include: bus-refresh  # 需要開啟的端點
        #exclude:             # 不需要開啟的端點

測試

檢視端點

訪問:http://localhost:9091/actuator 可以看到已經開啟了 bus-refresh 自動重新整理端點。

訪問:http://localhost:9091/name 和 http://localhost:9092/name 結果如下:

修改 Git 倉庫配置

修改 Git 倉庫配置資訊如下:

# 自定義配置
name: order-service-prod-1.0

自動重新整理

重新整理頁面發現結果並未改變,沒事正常。

通過 Post 方式呼叫「任意客戶端」的自動重新整理端點:http://localhost:9091/actuator/bus-refresh 再次訪問結果如下:

檢視佇列

再來觀察一下訊息佇列的 UI 介面,發現多了一個 springCloudBus 的交換機。

該交換機下綁定了兩個佇列對應我們的兩個 Config Client。

客戶端發起通知缺陷

  • 打破了微服務的職責單一性。微服務本身是業務模組,它本不應該承擔配置重新整理的職責。
  • 破壞了微服務各節點的對等性。
  • 存在一定的侷限性。例如,微服務在遷移時,它的網路地址常常會發生變化,此時如果想要做到自動重新整理,就不得不修改Webhook 的配置。

服務端發起通知

點選連結觀看:服務端發起通知視訊(獲取更多請關注公眾號「哈嘍沃德先生」)

為了解決客戶端發起通知缺陷,我們改用服務端發起通知。

  1. Webhook監聽被觸發,給 ConfigServer 傳送 bus-refresh 請求重新整理配置
  2. ConfigServer 傳送訊息給 Bus
  3. Bus 接收訊息後廣播通知所有 ConfigClient
  4. 各 ConfigClient 收到訊息重新讀取最新配置

新增依賴

Config Server 新增 spring cloud starter bus amqp 依賴。

<!-- spring cloud starter bus amqp 依賴 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

配置檔案

配置檔案需要配置 訊息佇列bus-refresh 自動重新整理端點。/actuator/bus-refresh 端點會清除 @RefreshScope 快取重新繫結屬性。

Config Server 的 application.yml 核心配置。

spring:
  application:
    name: config-server # 應用名稱
  cloud:
    config:
      server:
        git:
          uri: https://github.com/imrhelloworld/config-repo # 配置檔案所在倉庫地址
          #username:             # Github 等產品的登入賬號
          #password:             # Github 等產品的登入密碼
          #default-label: master # 配置檔案分支
          #search-paths:         # 配置檔案所在根目錄
  # 訊息佇列
  rabbitmq:
    host: 192.168.10.101
    port: 5672
    username: guest
    password: guest
    virtual-host: /

# 配置 Eureka Server 註冊中心
eureka:
  instance:
    prefer-ip-address: true       # 是否使用 ip 地址註冊
    instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port
  client:
    service-url:                  # 設定服務註冊中心地址
      defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/

# 度量指標監控與健康檢查
management:
  endpoints:
    web:
      base-path: /actuator    # 訪問端點根路徑,預設為 /actuator
      exposure:
        include: bus-refresh  # 需要開啟的端點
        #exclude:             # 不需要開啟的端點

測試

檢視端點

訪問:http://localhost:8888/actuator 可以看到已經開啟了 bus-refresh 自動重新整理端點。

訪問:http://localhost:9091/name 和 http://localhost:9092/name 結果如下:

修改 Git 倉庫配置

修改 Git 倉庫配置資訊如下:

# 自定義配置
name: order-service-prod-2.0

自動重新整理

重新整理頁面發現結果並未改變,沒事正常。

通過 Post 方式呼叫「任意服務端」的自動重新整理端點:http://localhost:8888/actuator/bus-refresh 再次訪問結果如下:

檢視佇列

再來觀察一下訊息佇列的 UI 介面,發現多了一個 springCloudBus 的交換機。

該交換機下綁定了四個佇列對應我們的兩個 Config Server 和兩個 Config Client。

區域性重新整理

假設有這樣一種場景,我們開發了一個新的功能,此時需要對該功能進行測試。我們只希望其中一個微服務的配置被更新,等功能測試完畢,正式部署線上時再更新至整個叢集。但是由於所有微服務都受 Spring Cloud Bus 的控制,我們更新了其中一個微服務的配置,就會導致其他服務也被通知去更新配置。這時候區域性重新整理的作用就體現出來了。

重新整理指定服務

修改 Git 倉庫配置資訊如下:

# 自定義配置
name: order-service-prod-3.0

通過 Post 方式呼叫「任意服務端」的自動重新整理端點:http://localhost:8888/actuator/bus-refresh/order-service:9091 再次訪問結果如下:

9091 埠的客戶端已經更新配置。

9092 埠的客戶端沒有更新配置。

重新整理指定叢集

假設現在功能測試完畢,需要正式部署線上更新至整個叢集。但是由於 Spring Cloud Bus 控制著多個微服務叢集(訂單微服務、商品微服務等),而我們只想更新指定叢集下的配置,這個時候就可以使用 Bus 提供的萬用字元更新方案。

修改 Git 倉庫配置資訊如下:

# 自定義配置
name: order-service-prod-4.0

通過 Post 方式呼叫「任意服務端」的自動重新整理端點:http://localhost:8888/actuator/bus-refresh/order-service:** 再次訪問結果如下:

至此 Bus 訊息匯流排所有的知識點就講解結束了。

本文采用 知識共享「署名-非商業性使用-禁止演繹 4.0 國際」許可協議

大家可以通過 分類 檢視更多關於 Spring Cloud 的文章。