參考:https://www.jianshu.com/p/997600098e6c
在普通單體應用,我們常使用配置文件(application(*).properties(yml))管理應用的所有配置。這些配置文件在單體應用中非常勝任其角色,並沒有讓我們感覺到有頭疼的地方。但隨着微服務框架的引入,微服務數量就會在我們產品中不斷增加,之前我們重點考慮的是系統的可伸縮、可擴展性好,但隨之就是配置管理的問題就會一一暴露出來。起初微服務器各自管各自的配置,在開發階段並沒什麼問題,但到了生產環境管理就會很頭疼,如果要大規模更新某項配置,困難就可想而知。
爲此,在分佈式系統中,Spring Cloud提供一個Config子項目,該項目核心就是配置中心,通過一個服務端和多個客戶端實現配置服務。我們可使用配置服務器集中的管理所有服務的各種環境配置文件。配置服務中心默認採用Git的方式進行存儲,因此我們很容易部署修改,並可以對環境配置進行版本管理。Spring Cloud Config具有中心化、版本控制、支持動態更新和語言獨立等特性。其特點是:
- 提供服務端和客戶端支持(Spring Cloud Config Server和Spring Cloud Config Client);
- 集中式管理分佈式環境下的應用配置;
- 基於Spring環境,實現了與Spring應用無縫集成;
- 可用於任何語言開發的程序;
- 默認實現基於Git倉庫(也支持SVN),從而可以進行配置的版本管理;
Spring Cloud Config的結構圖如下:
從圖中可以看出Spring Cloud Config有兩個角色(類似Eureka): Server和Client。Spring Cloud Config Server作爲配置中心的服務端承擔如下作用:
- 拉取配置時更新Git倉庫副本,保證是配置爲最新;
- 支持從yml、json、properties等文件加載配置;
- 配合Eureke可實現服務發現,配合Cloud Bus(這個後面我們在詳細說明)可實現配置推送更新;
- 默認配置存儲基於Git倉庫(可以切換爲SVN),從而支持配置的版本管理.
而對於,Spring Cloud Config Client則非常方便,只需要在啓動配置文件中增加使用Config Server上哪個配置文件即可。
構建Config-Server(idea)
pom如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
啓動類:
@SpringBootApplication
@EnableConfigServer
public class SpringCloundConfigDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloundConfigDemoApplication.class, args);
}
}
其中增加了@EnableConfigServer。
application.properties:
server.port=8890
spring.application.name=server-config
spring.cloud.config.server.git.uri=https://gitee.com/skyLogin/SpringCloundConfigGit.git
spring.cloud.config.server.git.username=登錄名
spring.cloud.config.server.git.password=密碼
這裏最重要的是需要配置Git倉庫的地址及登錄用戶名和口令。
我們在SpringCloundConfigGit倉庫中提交如下文件
user.properties:
project.name = sky
user-dev.properties:
project.description = dev-description
啓動測試:
{
"name": "user",
"profiles": ["dev"],
"label": null,
"version": "9bc698347dcb4e82e1c8fc631d7409cc3f0e6a65",
"state": null,
"propertySources": [{
"name": "https://gitee.com/skyLogin/SpringCloundConfigGit.git/user-dev.properties",
"source": {
"project.description": "dev-description"
}
}, {
"name": "https://gitee.com/skyLogin/SpringCloundConfigGit.git/user.properties",
"source": {
"project.name": "sky"
}
}]
}
這裏可以看到,我們提交到Git中的配置文件已經能夠被server-config正確的讀取到。
構建config-client
config-client可以是任何一個基於Spring boot的應用,這裏爲了講解方便,我們構建一個非常簡單的web工程。我們的config-client
項目需要引入對spring-cloud-starter-config
的依賴,如下:
pom:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
一個標準的Spring Boot啓動類:啓動類
@SpringBootApplication
public class SpringCloundConfigClientDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloundConfigClientDemoApplication.class, args);
}
}
這個測試Controller主要就是驗證我們可以從Git倉庫中獲取配置內容。編寫測試Controller
@RestController
public class ConfigController {
@Value("${project.name}")
String name;
@Value("${project.description}")
String description;
@RequestMapping("/config/get/message")
public String getMessage() {
return name + " - " + description;
}
}
這裏編寫的配置文件名稱爲:bootstrap.properties
,內容如下:編寫配置文件
server.port=8891
spring.application.name=user
spring.cloud.config.profile=dev
spring.cloud.config.uri= http://localhost:8890/
定義了微服務的名稱和profile以及配置服務器的地址。
注意: 這些配置不能夠配置在
application.properties
文件中,因爲在Spring Boot啓動時有引導上下文和應用上下文的概念,只有將配置服務器信息定義在引導上下文中,才能夠從配置服務器中獲取到配置信息。否則,服務啓動時會報找不到變量定義的錯誤。
啓動測試
說明,我們的config-client已經成功從server-config上獲取到配置的數據了。
Config Server配置文件映射關係
Config Server啓動以後,我們可以通過它暴露的端點獲取配置文件內容,http請求地址與配置文件映射關係如下:
# 映射{application}-{profile}.properties文件
/{application}/{profile}/[{label}]
/{label}/{application}-{profile}.properties
/{application}-{profile}.properties
/{label}/{application}-{profile}.yml
/{application}-{profile}.yml
{application}通常使用微服務名稱,對應Git倉庫中文件名的前綴;
{profile}對應{application}-後面的dev、pro、test等;
{label}對應Git倉庫的分支名,默認爲master。
Config Client從Config Server中獲取配置數據的流程:
1.Config Client 啓動時,根據 bootstrap.properties 中配置的應用名稱(application)、環境名(profile)和分支名(label),向 Config Server 請求獲取配置數據;
2.Config Server 根據 Config Client 的請求及配置,從Git倉庫(這裏以Git爲例)中查找符合的配置文件;
3.Config Server 將匹配到的Git倉庫拉取到本地,並建立本地緩存;
4.Config Server 創建Spring的 ApplicationContext 實例,並根據拉取的配置文件, 填充配置信息,然後將該配置信息返回給 Config Client ;
5.Config Client 獲取到 Config Server 返回的配置數據後,將這些配置數據加載到自己的上下文中。同時,因爲這些配置數據的優先級高於本地Jar包中的配置,因此將不再加載本地的配置。
那麼,Config Server 又是如何與Git倉庫中的配置文件進行匹配的呢?通常,我們會爲一個項目建立類似如下的配置文件:
mallweb.properties : 基礎配置文件;
mallweb-dev.properties : 開發使用的配置文件;
mallweb-test.properties : 測試使用的配置文件;
mallweb-prod.properties : 生產環境使用的配置文件;
當我們訪問 Config Server 的端點時,就會按照如下映射關係來匹配相應的配置文件:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
上面的Url將會映射爲格式爲:{application}-{profile}.properties(yml)的配置文件。另外, label 則對應Git上分支名稱,是一個可選參數,如果沒有則爲默認的 master 分支。
而 Config-Client 的 bootstrap.properties 配置對應如下:
spring.application.name application;
spring.cloud.config.profile profile;
spring.cloud.config.label label.
Config Server健康狀況
Config Server自帶了健康狀況指示器,暴露的endpoint爲/health,用於檢查配置的倉庫是否可用。對於文中的Config Server,請求http://localhost:8181/health返回如下結果
{
"status": "UP"
}
配置刷新
Config-Client中提供了一個 refresh
端點來實現配置文件的刷新。要想使用該功能,我們需要在Config-Client的pom.xml文件中增加以下依賴:
org.springframework.boot spring-boot-starter-actuator
這樣,當修改配置文件並提交到Git倉庫後,就可以使用: http://localhost:8080/refresh 刷新本地的配置數據。但是,最好的方式還是和Spring Cloud Bus進行整合,這樣才能實現配置的自動分發,而不是需要手工去刷新配置。