SpringCloud 配置中心Config和訊息匯流排Bus
一、概述
二、Config
三、Refresh
四、配置中心服務化
五、基於Webhook和訊息匯流排的解決方案
一、概述
SpringCloud配置中心包括Config和Bus兩個組成部分,只要這樣,才能保證主動推送。
下面主要分為四個部分,
Config講了基本的配置中心,但這樣如果修改配置客戶端在執行中是無法改變的。
Refresh講了我們修改配置檔案後可以向客戶端傳送一個POST請求,可以利用WebHook的方式。
配置中心服務化講了我們把配置中心獨立成一個服務(最好多掛幾個)掛到Eureka
基於Webhook和訊息匯流排的解決方案,讓我們客戶端可以實時的感知配置變化,從而做出改邊。
我們先看Config,然後整合Bus來達到我們配置中心的目的。
二、Config
1.Config概述
當一個系統配置檔案修改,我們需要重啟系統,但是微服務狀態下系統數量太多,為了方便服務配置檔案統一管理,實時更新,所以需要分散式配置中心元件。在Spring Cloud中,有分散式配置中心元件spring cloud config ,它支援配置服務放在配置服務的記憶體中(即本地),也支援放在遠端Git倉庫中。在spring cloud config 元件中,分兩個角色,一是config server,二是config client。
引入spring cloud config後,我們的外部配置檔案就可以集中放置在一個git倉庫裡,再新建一個config server,用來管理所有的配置檔案,維護的時候需要更改配置時,只需要在本地更改後,推送到遠端倉庫,所有的服務例項都可以通過config server來獲取配置檔案,這時每個服務例項就相當於配置服務的客戶端config client,為了保證系統的穩定,配置服務端config server可以進行叢集部署,即使某一個例項,因為某種原因不能提供服務,也還有其他的例項保證服務的繼續進行。
2.示例
⑴server
①新增依賴
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
②配置檔案
server: port: 8001 spring: application: name: spring-cloud-config-server cloud: config: server: git: uri: https://github.com/cGitHub123/Springcloud.git # 配置git倉庫的地址 search-paths: config-repo # git倉庫地址下的相對地址,可以配置多個,用,分割。 username: # git倉庫的賬號 password: # git倉庫的密碼
Spring Cloud Config也提供本地儲存配置的方式。我們只需要設定屬性spring.profiles.active=native,Config Server會預設從應用的src/main/resource目錄下檢索配置檔案。也可以通過spring.cloud.config.server.native.searchLocations=file:E:/properties/屬性來指定配置檔案的位置。雖然Spring Cloud Config提供了這樣的功能,但是為了支援更好的管理內容和版本控制的功能,還是推薦使用git的方式。
@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
④測試
返回值:
{
"name": "neo-config",
"profiles": [
"dev"
],
"label": null,
"version": null,
"state": null,
"propertySources": [
{
"name": "https://github.com/cGitHub123/Springcloud.git/config-repo/neo-config-dev.properties",
"source": {
"neo.hello": "hello im dev update"
}
}
]
}
上述的返回的資訊包含了配置檔案的位置、版本、配置檔案的名稱以及配置檔案中的具體內容,說明server端已經成功獲取了git倉庫的配置資訊。
如果直接檢視配置檔案中的配置資訊可訪問:http://localhost:8001/neo-config-dev.properties,返回:neo.hello: hello im dev
修改配置檔案neo-config-dev.properties中配置資訊為:neo.hello=hello im dev update,再次在瀏覽器訪問http://localhost:8001/neo-config-dev.properties,返回:neo.hello: hello im dev update。說明server端會自動讀取最新提交的內容
倉庫中的配置檔案會被轉換成web介面,訪問可以參照以下的規則:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
以neo-config-dev.properties為例子,它的application是neo-config,profile是dev。client會根據填寫的引數來選擇讀取對應的配置。
⑵Client端
①新增依賴
<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-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
②配置檔案
需要配置兩個配置檔案,application.properties和bootstrap.properties
application.properties如下:
spring.application.name=spring-cloud-config-client
server.port=8002
bootstrap.properties如下:spring.cloud.config.name=neo-config
spring.cloud.config.profile=dev
spring.cloud.config.uri=http://localhost:8001/
spring.cloud.config.label=master
spring.application.name:對應{application}部分spring.cloud.config.profile:對應{profile}部分
spring.cloud.config.label:對應git的分支。如果配置中心使用的是本地儲存,則該引數無用
spring.cloud.config.uri:配置中心的具體地址
spring.cloud.config.discovery.service-id:指定配置中心的service-id,便於擴充套件為高可用配置叢集。
特別注意:上面這些與spring-cloud相關的屬性必須配置在bootstrap.properties中,config部分內容才能被正確載入。因為config的相關配置會先於application.properties,而bootstrap.properties的載入也是先於application.properties。
③啟動類
@SpringBootApplication
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
}
④Web測試
使用@Value註解來獲取server端引數的值
@RestController
class HelloController {
@Value("${neo.hello}")
private String hello;
@RequestMapping("/hello")
public String from() {
return this.hello;
}
}
啟動專案後訪問:http://localhost:8002/hello,返回:hello im dev update說明已經正確的從server端獲取到了引數。到此一個完整的服務端提供配置服務,客戶端獲取配置引數的例子就完成了。我們在進行一些小實驗,手動修改neo-config-dev.properties中配置資訊為:neo.hello=hello im dev update1提交到github,再次在瀏覽器訪問http://localhost:8002/hello,返回:neo.hello: hello im dev update,說明獲取的資訊還是舊的引數,這是為什麼呢?因為springboot專案只有在啟動的時候才會獲取配置檔案的值,修改github資訊後,client端並沒有在次去獲取,所以導致這個問題。如何去解決這個問題呢?
三、Refresh
為了解決上面的問題,我們修改Client端,我們一修改配置,就給客戶端發個POST請求,我們不但要解決上面問題,還要讓客戶端主動感知提交的程式碼從而主動的更新:
1.新增依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
spring-boot-starter-actuator是一套監控的功能,可以監控程式在執行時狀態,其中就包括/refresh的功能。
需要給載入變數的類上面載入@RefreshScope,在客戶端執行/refresh的時候就會更新此類下面的變數值。
@RestController
@RefreshScope // 使用該註解的類,會在接到SpringCloud配置中心配置重新整理的時候,自動將新的配置更新到該類對應的欄位中。
class HelloController {
@Value("${neo.hello}")
private String hello;
@RequestMapping("/hello")
public String from() {
return this.hello;
}
}
在這種模式下,我們先請求服務端
http://localhost:8001/neo-config-dev.properties
返回:neo.hello: hello im dev update
然後我們請求客戶端
http://localhost:8002/hello
返回:hello im dev update bus
我們手動修改配置檔案,請求服務端:
neo.hello: hello im dev update bus edit
這時候我們手動執行:
curl -X POST http://localhost:8002/bus/refresh
請求客戶端:
neo.hello: hello im dev update bus edit
四、配置中心服務化
1.服務端改造
⑴新增依賴
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
⑵配置檔案
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8000/eureka/ ## 註冊中心eurka地址
⑶啟動類
啟動類新增@EnableDiscoveryClient啟用對配置中心的支援
@EnableDiscoveryClient
@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
然後我們啟動一個Eureka服務,再啟動上面的啟動類,可以看到已經註冊上去了,這裡我們可以將服務端改為高可用模式
2.客戶端改造
⑴新增依賴
<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.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
⑵配置檔案
spring.application.name=spring-cloud-config-client
server.port=8002
spring.cloud.config.name=neo-config
spring.cloud.config.profile=dev
spring.cloud.config.label=master
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=spring-cloud-config-server
eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
主要是去掉了spring.cloud.config.uri直接指向server端地址的配置,增加了最後的三個配置:spring.cloud.config.discovery.enabled :開啟Config服務發現支援
spring.cloud.config.discovery.serviceId :指定server端的name,也就是server端spring.application.name的值
eureka.client.serviceUrl.defaultZone :指向配置中心的地址
這三個配置檔案都需要放到bootstrap.properties的配置中
⑶啟動類
啟動類新增@EnableDiscoveryClient啟用對配置中心的支援
@EnableDiscoveryClient
@SpringBootApplication
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
}
啟動client端,在瀏覽器中訪問:http://localhost:8000/ 就會看到server端和client端都已經註冊了到註冊中心了。五、基於Webhook和訊息匯流排的解決方案
1.基本原理圖
這時Spring Cloud Bus做配置更新步驟如下:
⑴提交程式碼觸發post請求給bus/refresh
⑵server端接收到請求併發送給Spring Cloud Bus
⑶Spring Cloud bus接到訊息並通知給其它客戶端
⑷其它客戶端接收到通知,請求Server端獲取最新配置
⑸全部客戶端均獲取到最新的配置
2.客戶端
⑴新增依賴
需要多引入spring-cloud-starter-bus-amqp包,增加對訊息匯流排的支援
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
⑵修改配置檔案
## 重新整理時,關閉安全驗證
management.security.enabled=false
## 開啟訊息跟蹤
spring.cloud.bus.trace.enabled=true
spring.rabbitmq.host=192.168.9.89
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=123456
3.服務端
⑴新增依賴
需要多引入spring-cloud-starter-bus-amqp包,增加對訊息匯流排的支援
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
⑵修改配置檔案
server:
port: 8001
spring:
application:
name: spring-cloud-config-server
cloud:
config:
server:
git:
uri: https://github.com/ityouknow/spring-cloud-starter/ # 配置git倉庫的地址
search-paths: config-repo # git倉庫地址下的相對地址,可以配置多個,用,分割。
username: username # git倉庫的賬號
password: password # git倉庫的密碼
rabbitmq:
host: 192.168.0.6
port: 5672
username: admin
password: 123456
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8000/eureka/ ## 註冊中心eurka地址
management:
security:
enabled: false //配置檔案要注意格式,要不無效!!!
4.測試
我們將github上的檔案
neo.hello=hello im dev update bus edit edit
改成:neo.hello=hello im dev update bus edit edit zuizhong
然後執行一個CURL:
curl -X POST http://localhost:8001/bus/refresh
然後讀8001(配置伺服器端):
http://localhost:8001/neo-config-dev.properties
顯示:
neo.hello: hello im dev update bus edit edit zuizhong
然後我們讀:
8002客戶端:
http://localhost:8002/hello
輸出:
hello im dev update bus edit edit zuizhong
8003客戶端:
http://localhost:8003/hello
輸出:
hello im dev update bus edit edit zuizhong