1. 程式人生 > >spring cloud 使用spring cloud bus自動重新整理配置

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": "**:**"
  }
}...

 

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