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": "**:**"
}
}...
這樣,我們就可清晰地知道事件的傳播細節。