在前文服務(wù)注冊Eureka原理及集群配置中,我們配置Eureka集群時,可以通過--spring.profiles.active=peer1
來指定微服務(wù)在啟動時使用哪段配置。但往往在微服務(wù)架構(gòu)中,需要維護大量的配置文件,在開發(fā)、測試、生產(chǎn)環(huán)境,這些配置文件又有所不同,同時還希望能做到修改配置文件時,微服務(wù)能夠不停止服務(wù)。
也就是說在微服務(wù)架構(gòu)中,對于配置文件,通常有如下的需求
- 配置文件集中管理
- 不同環(huán)境不同配置
- 運行期間可動態(tài)調(diào)整配置
而Spring Cloud Config正是解決這問題的組件。
本文講從基本配置步驟,動態(tài)刷新配置,以及Spring cloud config高可用三個三面講解如何配置Spring cloud config.
配置步驟
如上圖所示,用戶將配置文件push到git倉庫,配置文件按照{application}-{profile}.yml
或者{application}-{profile}.properties
格式命名。spring cloud config server連接git倉庫,為所有config client(具體的微服務(wù)應(yīng)用)提供配置服務(wù)。
config client 在配置文件中指向配置中心的地址。
準備配置文件
創(chuàng)建一個 spring-cloud-config
文件夾,文件夾下創(chuàng)建子文件夾config
,在子文件夾下創(chuàng)建以下四個文件,并上傳本地gitlab倉庫中http://gitlab.bill.com/billjiang/spring-cloud-config
- hello.yml
- hello-dev.yml
- hello-test.yml
- hello-production.yml
創(chuàng)建config server
分別對應(yīng)默認、開發(fā)階段、測試階段、生成環(huán)境的配置文件,并在里面寫入相應(yīng)的內(nèi)容,比如依次寫入profile:defualt-1.0
、profile:dev-1.0
、profile:test-1.0
、profile:production-1.0
內(nèi)容,以便后續(xù)測試。
下面configserver項目為例,演示spring cloud config的配置,本文示例代碼參考springcloud-demo下的configserver
項目
- 創(chuàng)建configserver項目,引入如下依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
上面的pom.xml不僅引入了config-server還引入了security,主要是配置文件的信息比較重要,加上安全認證多個保障。
- 啟動類上加上
@EnableConfigServer
和@EnableDiscoveryClient
注解
這個注解聲明是config server,第二個注解是將其注冊到注冊中心,方便管理和橫向擴展為集群。 - 在配置文件中,加上如下配置
spring:
cloud:
config:
server:
git:
uri: http://gitlab.bill.com/billjiang/spring-cloud-config.git
search-paths: config
username: billjiang
password: '{cipher}2c50a112807ec405695dac19c15cc6da280d8d70e9998b82a9f11d202a6fb7b4'
health:
repositories:
a-hello:
label: master
name: hello
profiles: dev
security:
basic:
enabled: true
user:
name: user
password: 123456
encrypt:
key: billjiang
這里對配置文件進行了對稱加密,也可以對放入git倉庫(我在本地搭建了個gitlab)的敏感信息進行加密,對于密文的生成可以在項目啟動后,使用curl http://user:123456@localhost:8090/encrypt -d [明文]
這樣可以在控制臺生成密文,比如2c50a112807ec405695dac19c15cc6da280d8d70e9998b82a9f11d202a6fb7b4
,把生成的密文加上{cipher}
前綴即可作為對稱加密的信息。其中encrypt.key
是對稱加密的密鑰。
需要注意的是:如果使用Dalston.SR2
版本的Spring.cloud 在使用curl http://user:123456@localhost:8090/encrypt -d [明文]
會報錯,把Spring cloud換成Dalston.SR1
就能解決,這是Dalston.SR2
的一個bug。
啟動項目后,使用http://localhost:8090/hello/dev
可返回如下信息,說明config server已經(jīng)從git倉庫中讀取了hello-dev.yml
的配置信息
在瀏覽器輸入http://localhost:8090/hello-dev.yml
還可以在界面輸入配置文件的具體內(nèi)容。
創(chuàng)建config client
下面以hello
項目改造為例,說下client端如何從config server中獲取配置。
- 添加依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
- 在配置文件
bootstrap.yml
中添加如下配置
spring:
application:
name: hello
cloud:
config:
uri: http://user:123456@localhost:8090/
profile: dev
label: master
之所以不在application.yml中配置,spring boot會優(yōu)先加載bootstrap.yml,不然上下文中無法讀取到配置而報錯。這里指向了config server的地址,并且說明讀取hello-dev.yml
的配置,讀取的是master分支。
- 寫一個測試的列子
@Value("${profile}")
private String profile;
@GetMapping("/profile")
public String profile(){
return this.profile;
}
- 啟動
hello
項目,輸入http://localhost:8000/profile
即可在界面上看到dev-1.0
的輸出。說明客戶端正常讀取了指定的配置文件內(nèi)容。
配置刷新
要在微服務(wù)運行期間動態(tài)刷新配置,可以通過調(diào)用/refresh
實現(xiàn),但這樣只能針對單個服務(wù),而且要手動操作;如果通過消息中間件,可以將刷新事件廣播到所有相關(guān)的微服務(wù),從而做到自動刷新。
調(diào)用/refresh 刷新
- 引入依賴actuator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>1.5.6.RELEASE</version>
</dependency>`
- 配置文件中增加
endpoints:
refresh:
enabled: true
sensitive: false
- 修改配置文件
hello-dev.yml
內(nèi)容,改為dev-1.0-refresh
,提交到gitlab中 - 執(zhí)行
curl -X POST http://localhost:8000/refresh
或者用webhook提交該請求 - 瀏覽器輸入
http://localhost:8000/profile
查看輸出,發(fā)現(xiàn)內(nèi)容已經(jīng)更改為dev-1.0-refresh
使用Spring Cloud Bus自動刷新
借助Spring Cloud Bus,可以將配置變更事件廣播到相關(guān)微服務(wù),從而使得相關(guān)微服務(wù)能夠自動刷新配置。
那么刷新的事件可以從單個的服務(wù)發(fā)起,這樣可以將配置更新事件廣播到同類服務(wù)集群,如果N個微服務(wù)集群要更新服務(wù),那么也要操作N次。而從config server發(fā)起刷新,則所有相關(guān)集群自動刷新配置,后一種明顯更好。
config-server 配置spring-cloud-bus
- 引入 spring-cloud-bus
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
- 配置文件bootstrap.yml新增
endpoints:
bus:
enabled: true
sensitive: false
spring:
rabbitmq:
host: localhost
port: 5673
username: guest
password: guest
- 啟動項目
configserver
- 修改配置文件
hello-dev.yml
內(nèi)容為dev-1.0-bus
并提交到gitlab - 執(zhí)行
curl -X POST http://user:123456@localhost:8090/bus/refresh
刷新配置 - 瀏覽器輸入
http://localhost:8000/profile
發(fā)現(xiàn)內(nèi)容變?yōu)?code>dev-1.0-bus,說明自動化刷新已生效。
為了更好地測試上述效果,可以通過java -ar hello.jar --server.port=8001
,java -jar hello.jar --server.port=8002
命令將單個微服務(wù)配置成集群,同時配置其他集群。變更多個配置文件后,刷新配置,看看是否都更新了。
大家可以按照以上步驟,在單個服務(wù)節(jié)點上配置spring cloud bus,看看刷新配置后,集群中其他節(jié)點的配置是否同步更新了。
局部刷新
可以通過/bus/refresh?destination=customers:8000
,customers:8000
是注冊在Eureka Server上的微服務(wù)ID,即ApplicationContextID.
Spring cloud config高可用
作為微服務(wù)架構(gòu)中一個十分重要的服務(wù)節(jié)點,spring cloud config要保證高可用,就要避免單點。這里要分兩種情況,如果cloud server已經(jīng)注冊到Eureka Server,則僅僅需要多部署幾個cloud server形成集群。如果沒有注冊到Eureka Server,就需要通過負載均衡器,講請求轉(zhuǎn)發(fā)到cloud server集群。
當(dāng)然,也要保證消息中間件RabbitMQ的高可用。
以上就是Spring Cloud Config的配置。