技術背景
如今微服務架構盛行,在分布式系統中,項目日益龐大,子項目日益增多,每個項目都散落着各種配置文件,且隨着服務的增加而不斷增多。此時,往往某一個基礎服務信息變更,都會導致一系列服務的更新和重啟,運維也是苦不堪言,而且還很容易出錯。於是,配置中心便由此應運而生了。
目前市面上開源的配置中心有很多,像Spring家族的Spring Cloud Config, Apache的Apache Commons Configuration,淘寶的diamond, 百度的disconf, 360的QConf等等,都是為了解決這類問題。當下Spring體系大行其道,我們當然也優先選擇Spring Cloud Config了。
Spring Cloud Config
Spring Cloud Config 是一套為分布式系統中的基礎設施和微服務應用提供集中化配置的管理方案,它分為服務端與客戶端兩個部分。服務端也稱為分布式配置中心,它是一個獨立的微服務應用,用來連接配置倉庫並為客戶端提供獲取配置信息。客戶端則是微服務架構中的各個微服務應用或基礎設施,它們通過指定的配置中心來管理服務相關的配置內容,並在啟動的時候從配置中心獲取和加載配置信息。
Spring Cloud Config對服務端和客戶端中的環境變量和屬性配置 實現了抽象映射,所以它除了適用於 Spring 應用,也是可以在任何其他語言應用中使用的。Spring Cloud Config 實現的配置中心默認采用 Git 來存儲配置信息,所以使用 Spring Cloud Config 構建的配置服務器,天然就支持對微服務應用配置信息的版本管理,並且可以通過 Git 客戶端工具非常方便的管理和訪問配置內容。當然它也提供了對其他存儲方式的支持,比如:SVN 倉庫、本地化文件系統等。
實現案例
准備配置文件
首先在GIT下,新建config-reposity目錄,用來存放配置文件,如下圖所示,分別模擬了三個環境的配置文件。
分別編輯三個文件的,配置 spring.config.hello 屬性的值為 hello, this x env configurations.
服務端實現
新建工程
新建 spring-cloud-conifg-server 工程。
添加依賴
除了Spring Cloud依賴之外,添加配置中心依賴包。
pom.xml
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> </dependencies>
啟動類
啟動類添加注解 @EnableConfigServer,開啟配置服務支持。
ConfigServerApplication.java
package com.louis.spring.cloud.config.server; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.config.server.EnableConfigServer; @EnableConfigServer @SpringBootApplication public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } }
添加配置
修改配置文件,添加如下內容。如果是私有倉庫需要填寫用戶名密碼,如果是公開倉庫,可以不配置密碼。
application.yml
server: port: 8551 spring: application: name: spring-cloud-config-server cloud: config: server: git: uri: https://gitee.com/liuge1988/spring-cloud-demo/ # 配置git倉庫的地址 search-paths: config-repository # git倉庫地址下的相對地址,可以配置多個,用,分割。 username: username # git倉庫的賬號 password: password # git倉庫的密碼
Spring Cloud Config也提供本地存儲配置的方式,只需設置屬性spring.profiles.active=native
,Config Server會默認從應用的src/main/resource
目錄下檢索配置文件。另外也可以通過spring.cloud.config.server.native.searchLocations=file:D:/properties/
屬性來指定配置文件的位置。雖然Spring Cloud Config提供了這樣的功能,但是為了更好的支持內容管理和版本控制,還是比較推薦使用GIT的方式。
測試效果
啟動應用,訪問 http://localhost:8551/spring-config/dev,返回結果如下。
啟動應用,訪問 http://localhost:8551/spring-config/pro,返回結果如下。
上述的返回的信息包含了配置文件的位置、版本、配置文件的名稱以及配置文件中的具體內容,說明server端已經成功獲取了git倉庫的配置信息。
訪問:http://localhost:8551/spring-config-dev.properties,返回結果如下。
修改一下dev配置文件內容如下(末尾加了一個 update):
spring.config.hello=hello, this dev env configurations update.
再次訪問:http://localhost:8551/spring-config-dev.properties,返回結果如下。
發現讀取的是修改后提交的信息,說明服務端會自動讀取最新提交的數據。
倉庫中的配置文件會被轉換成相應的WEB接口,訪問可以參照以下的規則:
- /{application}/{profile}[/{label}]
- /{application}-{profile}.yml
- /{label}/{application}-{profile}.yml
- /{application}-{profile}.properties
- /{label}/{application}-{profile}.properties
以spring-config-dev.properties為例子,它的application是spring-config,profile是dev。client會根據填寫的參數來選擇讀取對應的配置。
客戶端實現
新建工程
新建 spring-cloud-conifg-client 工程。
添加依賴
添加相關依賴,添加WEB是為了測試接口。
pom.xml
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
添加配置
添加兩個配置文件如下。
application.yml
server: port: 8552 spring: application: name: spring-cloud-config-client
bootstrap.yml
spring: cloud: config: uri: http://localhost:8551/ # 配置中心的具體地址 name: spring-config # 對應{application}部分 profile: dev # 對應{profile}部分 label: master # 對應git的分支,如果配置中心使用的是本地存儲,則該參數無用
配置說明:
- spring.cloud.config.uri:配置中心的具體地址
- spring.cloud.config.name:對應{application}部分
- spring.cloud.config.profile:對應{profile}部分
- spring.cloud.config.label:對應git的分支。如果配置中心使用的是本地存儲,則該參數無用
- spring.cloud.config.discovery.service-id:指定配置中心的service-id,便於擴展為高可用配置集群。
特別注意:
上面這些與spring cloud相關的屬性必須配置在bootstrap.yml中,這樣config部分內容才能被正確加載。
因為config的相關配置會先於application.yml,而bootstrap.yml的加載也是先於application.yml文件的。
啟動類
啟動類無需添加額外注解。
ConfigClientApplication.java
package com.louis.spring.cloud.config.client; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ConfigClientApplication { public static void main(String[] args) { SpringApplication.run(ConfigClientApplication.class, args); } }
控制器
添加一個 HelloController 控制器, 添加注解 @Value("${spring.config.hello}"),聲明hello屬性從配置文件讀取。
HelloController.java
package com.louis.spring.cloud.config.client.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController class HelloController { @Value("${spring.config.hello}") private String hello; @RequestMapping("/hello") public String from() { return this.hello; } }
測試效果
先后啟動配置中心服務端和客戶端, 訪問 http://localhost:8552/hello,效果如下。
說明客戶端已經成功從服務端讀取了配置信息。
現在手動修改一下倉庫配置文件的內容,末尾加個數字 2,修改完成並提交。
再次訪問 http://localhost:8552/hello,效果如下。
我們發現返回結果並沒有讀取最新提交的內容,這是因為Spring Boot項目只有在啟動的時候才會獲取配置文件的內容,雖然GIT配置信息被修改了,但是客戶端並沒有重新去獲取,所以導致讀取的信息仍然是舊配置。那么該如何去解決這個問題呢?這就是我們下一章要講的 Spring Cloud Bus。
配置中心服務化
到目前為止,我們的客戶端都是直接調用配置中心的server端來獲取配置文件信息。這樣客戶端和服務端的耦合性太高,如果server端要做集群,客戶端只能通過原始的方式來路由,server端改變IP地址的時候,客戶端也需要修改配置,不符合Spring Cloud服務治理的理念。所以我們需要將服務端也當做一個服務注冊到注冊中心,客戶端去注冊中心獲取配置中心服務就可以了。
打開 spring-cloud-conifg-server,修改服務端POM,添加注冊中心依賴。
pom.xml
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency>
啟動類添加注解 @EnableDiscoveryClient,提供服務發現支持。
ConfigServerApplication.java
package com.louis.spring.cloud.config.server; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.config.server.EnableConfigServer; @EnableConfigServer @EnableDiscoveryClient @SpringBootApplication public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } }
修改配置,添加服務注冊信息。
application.yml
server: port: 8551 spring: application: name: spring-cloud-config-server cloud: consul: host: localhost port: 8500 discovery: serviceName: ${spring.application.name} # 注冊到consul的服務名稱 config: server: git: uri: https://gitee.com/liuge1988/spring-cloud-demo/ # 配置git倉庫的地址 search-paths: config-repository # git倉庫地址下的相對地址,可以配置多個,用,分割。 username: username # git倉庫的賬號 password: password # git倉庫的密碼
先后啟動注冊中心服務器,配置中心服務器, 訪問 http://localhost:8500,確認注冊中心注冊成功。
訪問 http://localhost:8551/config-server/dev,也能成功讀取配置,服務端就算改造好了。
打開 spring-cloud-conifg-client,修改服務端POM,添加注冊中心依賴。
pom.xml
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency>
啟動類添加注解 @EnableDiscoveryClient,提供服務發現支持。
ConfigClientApplication.java
package com.louis.spring.cloud.config.client; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @EnableDiscoveryClient @SpringBootApplication public class ConfigClientApplication { public static void main(String[] args) { SpringApplication.run(ConfigClientApplication.class, args); } }
修改配置文件,移除uri的直接地址配置,開啟服務發現並配置serviceId為注冊中心服務器的服務名稱。
bootstrap.yml
spring: cloud: consul: host: localhost port: 8500 discovery: serviceName: spring-cloud-config-client # 注冊到consul的服務名稱 config: discovery: enabled: true # 開啟服務發現 serviceId: spring-cloud-config-server # 配置中心服務名稱 name: spring-config # 對應{application}部分 profile: dev # 對應{profile}部分 label: master # 對應git的分支,如果配置中心使用的是本地存儲,則該參數無用
啟動客戶端,訪問 http://localhost:8552/hello,成功讀取配置信息,說明客戶端也改造完成了。
源碼下載
碼雲:https://gitee.com/liuge1988/spring-cloud-demo.git
作者:朝雨憶輕塵
出處:https://www.cnblogs.com/xifengxiaoma/
版權所有,歡迎轉載,轉載請注明原文作者及出處。