Spring Cloud Config 統一配置中心java
一般,咱們會使用配置文件來管理應用的配置。如一個 Spring Boot 的應用,能夠將配置信息放在 application.yml 文件中,若是須要多環境配置,能夠設置多個 application-{profile}.yml,再經過 spring.profiles.active={profile} 來實現多環境的切換。這樣的管理對於單體應用或者說劃分的服務很少的狀況下沒什麼問題,但若是是一個微服務架構的應用系統有着不少個微服務,集中管理配置就很是必要了git
對於這樣的配置管理,咱們會但願它github
Spring Cloud Config 爲分佈式系統外部化配置提供了服務器端和客戶端的支持,分爲 Config Server 和 Config Clientspring
Config Server 是用來集中管理應用程序的各個環境下的配置,默認是使用 Git 來存儲配置內容的,能夠很方便的對配置實現版本管理(也支持 Subversion 和本地化文件系統存儲)json
Config Client 即用來獲取 Config Server 中存儲的配置內容bootstrap
建立一個 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 倉庫的相關信息app
application.ymlmaven
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/
目錄下創建以下的配置文件
每一個文件中分別填入以下配置內容
Config Server 的端點
使用 Config Server 的端點能夠獲取配置文件的內容,請求地址與配置文件的映射以下:
上面的地址均可以映射到 {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 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 中的配置文件中的屬性,其中
另外這些均可以經過設置 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.profile; } }