Spring Cloud Config 統一配置中心
Spring Cloud Config 統一配置中心
一、統一配置中心
統一管理配置
通常,我們會使用配置檔案來管理應用的配置。如一個 Spring Boot 的應用,可以將配置資訊放在 application.yml 檔案中,如果需要多環境配置,可以設定多個 application-{profile}.yml,再通過 spring.profiles.active={profile} 來實現多環境的切換。這樣的管理對於單體應用或者說劃分的服務不多的情況下沒什麼問題,但如果是一個微服務架構的應用系統有著很多個微服務,集中管理配置就非常必要了
對於這樣的配置管理,我們會希望它
- 集中化管理配置
- 多環境多配置
- 可動態調整並自動更新
Spring Cloud Config 配置中心
Spring Cloud Config 為分散式系統外部化配置提供了伺服器端和客戶端的支援,分為 Config Server 和 Config Client
Config Server 是用來集中管理應用程式的各個環境下的配置,預設是使用 Git 來儲存配置內容的,可以很方便的對配置實現版本管理(也支援 Subversion 和本地化檔案系統儲存)
Config Client 即用來獲取 Config Server 中儲存的配置內容
二、使用
建立 Config Server
建立一個 Spring Boot 工程,maven 新增 spring-cloud-config-server
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
在程式啟動類上添加註解 @EnableConfigServer
,開啟配置伺服器的功能
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
Config Server 預設是使用 Git 來儲存配置內容的,下面來配置下 git 倉庫的相關資訊
application.yml
server:
port: 8888
spring:
application:
name: config-server
cloud:
config:
server:
git:
# git 倉庫地址
uri: https://github.com/Morgan412/weixin-order
# 倉庫下的搜尋路徑
search-paths: conf
# git倉庫賬號
username:
# git倉庫密碼
password:
如果是公開倉庫可以不用賬號和密碼,在倉庫的 conf/
目錄下建立如下的配置檔案
- product.yml
- product-dev.yml
- product-pro.yml
每個檔案中分別填入如下配置內容
- profile: default
- profile: dev
- profile: pro
Config Server 的端點
使用 Config Server 的端點可以獲取配置檔案的內容,請求地址與配置檔案的對映如下:
- /{application}/{profile}[/{label}]
- /{application}-{profile}.yml
- /{label}/{application}-{profile}.yml
- /{application}-{profile}.properties
- /{label}/{application}-{profile}.properties
上面的地址都可以對映到 {application}-{profile}.properties/yml
配置檔案,{label}
表示對應 Git 倉庫的分支,預設是 master
啟動上面的 config-server 專案,通過 url 訪問遠端 Git 倉庫 master 分支下 conf 目錄下的 product-dev.yml
配置檔案內容
通過 http://localhost:8888/product/dev 訪問,可以獲得應用名稱、profile、git label、git version、配置檔案URL、配置內容等資訊
{
"name": "product",
"profiles": [
"dev"
],
"label": null,
"version": "052661b72043aad390e6774666b5594d6e0ba116",
"state": null,
"propertySources": [
{
"name": "https://github.com/Morgan412/weixin-order/conf/product-dev.yml",
"source": {
"profile": "dev"
}
},
{
"name": "https://github.com/Morgan412/weixin-order/conf/product.yml",
"source": {
"profile": "default"
}
}
]
}
而 http://localhost:8888/product-dev.yml 和 http://localhost:8888/product-dev.properties 只會獲取到配置檔案中的屬性,包括 {application}.yml/properties
中的屬性
配置 Config Client
上面建立了一個 Config Server 來集中管理配置,那下面來配置 Config Client 讓微服務獲取配置資訊
同樣是建立一個 Spring Boot 工程,新增 Config Client 的依賴,這裡省略了其他依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
相關配置如下
server:
port: 8082
spring:
application:
# 對應 config server 所獲取的配置檔案 {application}
name: product
cloud:
config:
# 指定 config server 的地址,預設是 http://localhost:8888
uri: http://localhost:8888
# 對應配置檔案的 {profile}
profile: dev
# 分支
label: master
上面的配置可以從 /{application}/{profile}/{label}
獲取對應 config server 中的配置檔案中的屬性,其中
- application 對應 ${spring.application.name}
- profile 對應 ${spring.profiles.active} (實際就是 Environment.getActiveProfiles())
- label 是儲存倉庫的分支,預設是 master
另外這些都可以通過設定 spring.cloud.config.*
(*
為 name
、profile
、label
) 來覆蓋
如果這時就啟動該服務,就可能會出現一些問題,因為上面關於 config client 的配置需要放到 bootstrap.yml
而不是 application.yml
。
我們來想一個問題,我們交給 config server 集中管理的配置內容是不是原本應該放在 application.yml
中在程式啟動的時候被載入的,而現在我們把獲取配置內容的 config client 相關配置放在了 application.yml
中,這樣是不是就有點不對了,因為這裡會出現一個先後順序的問題。如果我們把配置放在了 application.yml
中,那麼它會先去載入 bootstrap.yml
的配置屬性(如果沒有,會載入預設配置),假如我們在 application.yml
中配置的 uri 埠是 8080,那麼它將不會被應用,還是預設的 8888 埠
Spring Cloud 有一個 引導上下文 的概念,它是主應用程式的父上下文,這個引導上下文負責從外部源(配置伺服器,如Config Server)載入配置屬性,及解密外部配置檔案中的屬性。主應用程式載入的是 application.(properties/yml) 中的屬性,引導上下文載入 bootstrap.(properties/yml) 中的屬性。這兩個上下文共享一個
Environment
,但配置在 boostrap.* 中的屬性有更高的優先順序,因此預設情況下不能被本地配置覆蓋。設定
spring.cloud.bootstrap.enabled=false
可以禁用引導過程
可以來寫個 Controller 來測試一下獲取配置
@RestController
class ConfigClientController {
@Value("${profile}")
private String profile;
@RequestMapping("/profile")
public String getProfile() {
return this.profi