spring cloud 使用spring cloud bus自動刷新配置


Spring Cloud Bus提供了批量刷新配置的機制,它使用輕量級的消息代理(例如RabbitMQ、Kafka等)連接分布式系統的節點,這樣就可以通過Spring Cloud Bus廣播配置的變化或者其他的管理指令。使用Spring Cloud Bus后的架構如圖9-2所示。

圖9-2 使用Spring Cloud Bus的架構圖

由圖可知,微服務A的所有實例通過消息總線連接到了一起,每個實例都會訂閱配置更新事件。當其中一個微服務節點的/bus/refresh端點被請求時,該實例就會向消息總線發送一個配置更新事件,其他實例獲得該事件后也會更新配置。

下面我們以RabbitMQ為例,為大家講解如何使用Spring Cloud Bus實現配置的自動刷新。

(1) 安裝RabbitMQ。RabbitMQ的安裝非常簡單,本書不再贅述。

(2) 創建項目microservice-config-client-refresh-cloud-bus 

(3) 為項目添加spring-cloud-starter-bus-amqp 的依賴。

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

(4) 在bootstrap.yml中添加以下內容:

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

  management:
    security:
      enabled: false #是否開啟actuator安全認證

 

測試

(1) 啟動microservice-config-server

(2) 啟動microservice-config-client-refresh-cloud-bus,可發現此時控制台打印類似於以下的內容:

[           main] 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)

說明此時有一個/bus/refresh 端點

(3) 將microservice-config-client-refresh-cloud-bus的端口改成8082,再啟動一個節點。

(4) 訪問http://localhost:8081/profile ,可獲得結果:dev-1.0。

(4) 將git倉庫中的microservice-foo-dev.properties文件內容改為profile=dev-1.0-bus

(5) 發送POST請求到其中一個Config Client節點的的/bus/refresh端點,例如:

curl -X POST http://localhost:8081/bus/refresh

借助Git倉庫的WebHook,我們就可輕松實現配置的自動刷新。如圖9-3所示。

圖9-3 Git WebHooks設置

借助Git倉庫的WebHook,我們就可輕松實現配置的自動刷新。如圖9-3所示。(6) 訪問兩個Config Client節點的/profile端點,會發現兩個節點都會返回dev-1.0-bus ,說明配置內容已被刷新。

局部刷新

某些場景下(例如灰度發布),我們可能只想刷新部分微服務的配置,此時可通過/bus/refresh端點的destination參數來定位要刷新的應用程序。

例如:/bus/refresh?destination=customers:9000 ,這樣消息總線上的微服務實例就會根據destination參數的值來判斷是否需要要刷新。其中,customers:9000 指的是各個微服務的ApplicationContext ID。

destination參數也可以用來定位特定的微服務。例如:/bus/refresh?destination=customers:**,這樣就可以觸發customers微服務所有實例的配置刷新。

擴展閱讀:關於ApplicationContext ID

默認情況下,ApplicationContext ID是spring.application.name:server.port,詳見org.springframework.boot.context.ContextIdApplicationContextInitializer.getApplicationId(ConfigurableEnvironment)方法。

http://www.itmuch.com/spring-cloud-code-read/spring-cloud-code-read-spring-cloud-bus/

架構改進

在前面的示例中,我們通過請求某個微服務的/bus/refresh端點的方式來實現配置刷新,但這種方式並不優雅。原因如下:

(1) 打破了微服務的職責單一性。微服務本身是業務模塊,它本不應該承擔配置刷新的職責。

(2) 破壞了微服務各節點的對等性。

(3) 有一定的局限性。例如,微服務在遷移時,它的網絡地址常常會發生變化,此時如果想要做到自動刷新,那就不得不修改WebHook的配置。

我們不妨改進一下我們的架構。

圖9-4 使用Spring Cloud Bus的架構圖

如圖9-4,我們將Config Server也加入到消息總線中,並使用Config Server的/bus/refresh端點來實現配置的刷新。這樣,各個微服務只需要關注自身的業務,而不再承擔配置刷新的職責。

1.在springcloud-configServer中配置bus,加入pom依賴

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

2.springcloud-configServer中配置bus ym文件

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
  management:
    security:
      enabled: false #是否開啟actuator安全認證

3.在微服務端springcloud-ssmServer配置bus接收

pom.xml

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

application.properties

#mq
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

management.security.enabled=false

在需要自動刷新的位置加入@RefreshScope 例如

package com.pupeiyuan.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RefreshScope public class ConfigClientController { @Value("${multiple.datasource.master.InitialSize}") private String profile; @GetMapping("/profile") public String getProfile() { return this.profile; } }

利用webhook自動請求,配置/bus/refresh到springcloud-configServer項目,springcloud-configServer在利用bus傳播特性,通過mq傳播到指定客戶端進行更新

跟蹤總線事件

一些場景下,我們可能希望知道Spring Cloud Bus事件傳播的細節。此時,我們可以跟蹤總線事件(RemoteApplicationEvent的子類都是總線事件)。

跟蹤總線事件非常簡單,只需設置spring.cloud.bus.trace.enabled=true ,這樣在/bus/refresh端點被請求后,訪問/trace端點就可獲得類似如下的結果:

{ "timestamp": 1481098786017, "info": { "signal": "spring.cloud.bus.ack", "event": "RefreshRemoteApplicationEvent", "id": "66d172e0-e770-4349-baf7-0210af62ea8d", "origin": "microservice-foo:8081", "destination": "**" } },{ "timestamp": 1481098779073, "info": { "signal": "spring.cloud.bus.sent", "type": "RefreshRemoteApplicationEvent", "id": "66d172e0-e770-4349-baf7-0210af62ea8d", "origin": "microservice-config-server:8080", "destination": "**:**" } }...

 

這樣,我們就可清晰地知道事件的傳播細節。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM