一、簡介
在分布式系統(tǒng)中,由于服務(wù)數(shù)量巨多,為了方便服務(wù)配置文件統(tǒng)一管理,實(shí)時(shí)更新,所以需要分布式配置中心組件。在Spring Cloud中,有分布式配置中心組件spring cloud config ,它支持配置服務(wù)放在配置服務(wù)的內(nèi)存中(即本地),也支持放在遠(yuǎn)程Git倉庫中。在spring cloud config 組件中,分兩個(gè)角色,一是config server,二是config client。
隨著線上項(xiàng)目變的日益龐大,每個(gè)項(xiàng)目都散落著各種配置文件,如果采用分布式的開發(fā)模式,需要的配置文件隨著服務(wù)增加而不斷增多。某一個(gè)基礎(chǔ)服務(wù)信息變更,都會(huì)引起一系列的更新和重啟,運(yùn)維苦不堪言也容易出錯(cuò)。配置中心便是解決此類問題的靈丹妙藥。
市面上開源的配置中心有很多,BAT每家都出過,360的QConf、淘寶的diamond、百度的disconf都是解決這類問題。國外也有很多開源的配置中心Apache的Apache Commons Configuration、owner、cfg4j等等。
二、配置中心提供的核心功能
- 提供服務(wù)端和客戶端支持
- 集中管理各環(huán)境的配置文件
- 配置文件修改之后,可以快速的生效
- 可以進(jìn)行版本管理
- 支持大的并發(fā)查詢
- 支持各種語言
Spring Cloud Config可以完美的支持以上所有的需求。
Spring Cloud Config項(xiàng)目是一個(gè)解決分布式系統(tǒng)的配置管理方案。它包含了Client和Server兩個(gè)部分,server提供配置文件的存儲(chǔ)、以接口的形式將配置文件的內(nèi)容提供出去,client通過接口獲取數(shù)據(jù)、并依據(jù)此數(shù)據(jù)初始化自己的應(yīng)用。Spring cloud使用git或svn存放配置文件,默認(rèn)情況下使用git,我們以git為例。
首先在github上面創(chuàng)建了一個(gè)文件夾 config-files用來存放配置文件,為了模擬生產(chǎn)環(huán)境,我們創(chuàng)建以下三個(gè)配置文件:
// 開發(fā)環(huán)境
mengma-config-dev.yml
// 測試環(huán)境
mengma-config-test.yml
// 生產(chǎn)環(huán)境
mengma-config-pro.yml
每個(gè)配置文件中都寫一個(gè)屬性 hello ,屬性值分別是 mengma.....dev / mengma.....test / mengma.....pro 。下面我們開始配置config server 端。
config server 端代碼編寫
- 新建項(xiàng)目,引入依賴,只需要引入 config -server 就可以 ,不需要引入 eureka-client ,web
config-server
- 配置配置文件
server:
port: 8778
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/*** # 配置git倉庫的地址
search-paths: config-files # git倉庫地址下的相對(duì)地址,可以配置多個(gè),用,分割。
username: *** # git倉庫的賬號(hào)
password: **** # git倉庫的密碼
- 啟動(dòng)類添加注解
@SpringBootApplication
// 聲明為 config server 端
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
- 測試config server 是否生效
首先我們先要測試server端是否可以讀取到github上面的配置信息,直接訪問:http://localhost:8778/mengma-config/dev
返回信息如下:
{
"name": "mengma-config",
"profiles": [
"dev"
],
"label": null,
"version": null,
"state": null,
"propertySources": [
{
"name": "https://github.com/****/config-files/mengma-config-dev.yml",
"source": {
"hello": "mengma.....dev"
}
}
]
}
上述的返回的信息包含了配置文件的位置、版本、配置文件的名稱以及配置文件中的具體內(nèi)容,說明server端已經(jīng)成功獲取了git倉庫的配置信息。
如果直接查看配置文件中的配置信息可訪問:http://localhost:8778/mengma-config-dev.yml,
返回:
hello: mengma.....dev
修改配置文件mengma-config-dev.yml中配置信息為:hello: mengma.....dev update,再次在瀏覽器訪問http://localhost:8778/mengma-config-dev.yml,返回:
hello: mengma.....dev update、
說明 server 端會(huì)自動(dòng)讀取最新提交的內(nèi)容。
倉庫中的配置文件會(huì)被轉(zhuǎn)換成web接口,訪問可以參照以下的規(guī)則:
- /{application}/{profile}[/{label}]
- /{application}-{profile}.yml
- /{label}/{application}-{profile}.yml
- /{application}-{profile}.properties
- /{label}/{application}-{profile}.properties
以config-server-dev.yml為例子,它的 application 是 config-server,profile是dev,client會(huì)根據(jù)填寫的參數(shù)來選擇讀取對(duì)應(yīng)的配置。
label?.....
以config-server-dev.yml為例子,它的application是config-server,profile是dev。client會(huì)根據(jù)填寫的參數(shù)來選擇讀取對(duì)應(yīng)的配置。
client 端
主要展示如何在業(yè)務(wù)項(xiàng)目中去獲取server端的配置信息。
添加依賴
spring-cloud-starter-config
spring-boot-starter-web
spring-boot-starter-test配置文件
需要配置兩個(gè)配置文件,application.properties和bootstrap.properties(文件加載優(yōu)先權(quán))
application.properties如下:
spring.application.name=spring-cloud-config-client
server.port=8002
bootstrap.properties如下:
spring.application.name=config-client
spring.cloud.config.label=master
spring.cloud.config.profile=dev
spring.cloud.config.uri= http://localhost:xxxx/
server.port=8881
- spring.cloud.config.label 指明遠(yuǎn)程倉庫的分支
- spring.cloud.config.profile
dev開發(fā)環(huán)境配置文件
test測試環(huán)境
pro正式環(huán)境 - spring.cloud.config.uri= http://localhost:8888/ 指明配置服務(wù)中心的網(wǎng)址。
程序的入口類,寫一個(gè)API接口“/hi”,返回從配置中心讀取的 hello 變量的值,代碼如下:
@SpringBootApplication
@RestController
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
@Value("${hello}")
String hello;
@RequestMapping(value = "/hi")
public String hi(){
return hello;
}
}
打開網(wǎng)址訪問:http://localhost:8881/hi,網(wǎng)頁顯示:
mengma.....dev
這就說明,config-client從config-server獲取了foo的屬性,而config-server是從git倉庫讀取的,如圖:
配置中心服務(wù)高可用
客戶端都是直接調(diào)用配置中心的server端來獲取配置文件信息。這樣就存在了一個(gè)問題,客戶端和服務(wù)端的耦合性太高,如果server端要做集群,客戶端只能通過原始的方式來路由,server端改變IP地址的時(shí)候,客戶端也需要修改配置,不符合springcloud服務(wù)治理的理念。springcloud提供了這樣的解決方案,我們只需要將server端當(dāng)做一個(gè)服務(wù)注冊(cè)到eureka中,client端去eureka中去獲取配置中心server端的服務(wù)既可。
這篇文章我們基于配置中心git版本的內(nèi)容來改造。
server 端改造
- 添加依賴
添加 eureka-client 依賴,來添加對(duì)eureka 的支持。
- 配置文件
server:
server:
port: 8001
spring:
application:
name: spring-cloud-config-server
cloud:
config:
server:
git:
uri: https://github.com/***/spring-cloud-starter/ # 配置git倉庫的地址
search-paths: config-repo # git倉庫地址下的相對(duì)地址,可以配置多個(gè),用,分割。
username: username # git倉庫的賬號(hào)
password: password # git倉庫的密碼
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8000/eureka/ ## 注冊(cè)中心eurka地址
增加了eureka注冊(cè)中心的配置。
這樣server端的改造就完成了。先啟動(dòng)eureka注冊(cè)中心,在啟動(dòng)server端,在瀏覽器中訪問:http://localhost:xxxx/ 就會(huì)看到server端已經(jīng)注冊(cè)了到注冊(cè)中心了。
客戶端改造
依賴添加
添加 eureka-client配置文件
spring:
cloud:
config:
discovery:
serviceId: spring-cloud-config-server
enabled: true
profile: dev
name: neo-config
label: master
application:
name: spring-cloud-config-client
server:
port: 8002
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8000/eureka/
主要是去掉了spring.cloud.config.uri直接指向server端地址的配置,增加了最后的三個(gè)配置:
spring.cloud.config.discovery.enabled :開啟Config服務(wù)發(fā)現(xiàn)支持
spring.cloud.config.discovery.serviceId :指定server端的name,也就是server端spring.application.name的值
eureka.client.serviceUrl.defaultZone :指向配置中心的地址
這三個(gè)配置文件都需要放到bootstrap.yml的配置中。
啟動(dòng)client端,在瀏覽器中訪問:http://localhost:xxxx/ 就會(huì)看到server端和client端都已經(jīng)注冊(cè)了到注冊(cè)中心了。

高可用
為了模擬生產(chǎn)集群環(huán)境,我們改動(dòng)server端的端口為8003,再啟動(dòng)一個(gè)server端來做服務(wù)的負(fù)載,提供高可用的server端支持。

如上圖就可發(fā)現(xiàn)會(huì)有兩個(gè)server端同時(shí)提供配置中心的服務(wù),防止某一臺(tái)掛掉之后影響整個(gè)系統(tǒng)的使用。
我們先單獨(dú)測試服務(wù)端,分別訪問:http://localhost:8001/neo-config/dev、http://localhost:8003/neo-config/dev返回信息:
再次訪問:http://localhost:8002/hello,返回:mengma.....dev update。說明客戶端已經(jīng)讀取到了server端的內(nèi)容,我們隨機(jī)停掉一臺(tái)server端的服務(wù),再次訪問http://localhost:8002/hello,返回:mengma.....dev update,說明達(dá)到了高可用的目的。