Spring Cloud實戰系列(六) - 分散式配置中心Spring Cloud Config
在 分散式系統 中,由於服務數量巨多,為了方便 服務配置檔案 的 統一管理 和 實時更新 ,所以需要 分散式配置中心 元件。 Spring Cloud
提供的 分散式配置中心 元件是 Spring Cloud Config
,它支援將 配置服務 放在配置服務的 記憶體 中(即 本地 ),也支援放在 遠端 Git
倉庫中。 Spring Cloud Config
提供了兩個角色,一個是 Config Server
,二個是 Config Client
。
正文
1. Config Server從本地讀取配置檔案
建立一個新的 Spring Boot
專案模組,取名為 config-server
,它的 pom.xml
配置如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>io.github.ostenant.springcloud</groupId> <artifactId>config-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>config-server</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Dalston.RELEASE</spring-cloud.version> </properties> <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>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 複製程式碼
在應用啟動類上使用 註解 @EnableConfigServer
開啟 配置伺服器 。
@EnableConfigServer @SpringBootApplication public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } } 複製程式碼
需要在程式的 配置檔案 application.properties
裡面進行如下配置。通過 spring.profile.active=native
來配置 Config Server
從 本地讀取配置 ,讀取的路徑為 Classpath
下的 shared
目錄。
server: port: 8769 spring: application: name: config-server profiles: active: native cloud: config: server: native: search-locations: classpath:/shared 複製程式碼
在 src/main/resources
目錄下新建 shared
資料夾,在 shared
資料夾下新建一個 config-client-dev.yml
檔案。
server: port: 8762 foo: foo version 1 複製程式碼
執行 ConfigServerApplication
的 main()
方法,在 8769
埠啟動 Config Server
應用程式。
2. 構建Config Client
建立一個 Spring Boot
專案模組,取名為 config-client
,它的 pom.xml
配置如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>io.github.ostenant.springcloud</groupId> <artifactId>config-client</artifactId> <version>0.0.1-SNAPSHOT</version> <name>config-client</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Dalston.RELEASE</spring-cloud.version> </properties> <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> <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>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 複製程式碼
在 resources
目錄下新建 bootstrap.yml
檔案,因為 bootstrap
相對於 application
具有 優先的執行順序 。
變數 {spring.application.name}
和 {spring.profiles.active}
,兩者使用 “-”
相連,作為 Config Client
向 Config Server
讀取的 配置檔名 。
bootstrap.yml
spring: application: name: config-client cloud: config: uri: http://localhost:8769 fail-fast: true # 讀取沒有成功,執行快速失敗 profiles: active: dev 複製程式碼
配置一個介面,用於測試 讀取配置檔案 的 foo
變數,並通過 API
介面返回客戶端。
@RestController @SpringBootApplication public class ConfigClientApplication { public static void main(String[] args) { SpringApplication.run(ConfigClientApplication.class, args); } @Value("${foo}") private String foo; @RequestMapping(value = "/foo") public String foo(){ return foo; } } 複製程式碼
啟動 config-client
應用程式,訪問 http://localhost:8762/foo
,服務端的響應資料如下:
foo version 1
可見 config-client
成功地從 config-server
專案的 shared
本地檔案目錄 讀取到 配置檔案 config-client-dev.yml
中的 foo
變數。
3. Config Server從遠端Git倉庫讀取配置檔案
修改 config-server
的配置檔案 application.yml
,程式碼如下.
server: port: 8769 spring: application: name: config-server cloud: config: server: git: uri: https://coding.net/ostenant/config-repo search-paths: test username: [email protected] password: xxxx label: master 複製程式碼
如果 Git
倉庫為 公開倉庫 ,可以不填寫 使用者名稱 和 密碼 ;如果是 私有倉庫 則需要填寫,本例子配置了一個 私有倉庫 。
配置 | 解釋 |
---|---|
spring.cloud.config.server.git.uri | 配置git倉庫地址 |
spring.cloud.config.server.git.searchPaths | 配置倉庫路徑 |
spring.cloud.config.label | 配置倉庫的分支 |
spring.cloud.config.server.git.username | 訪問git倉庫的使用者名稱 |
spring.cloud.config.server.git.password | 訪問git倉庫的使用者密碼 |
遠端倉庫 https://coding.net/ostenant/config-repo
中有個 名為 config-client-dev.properties
的 配置檔案 ,裡面配置有一個屬性:
foo = foo version 2 複製程式碼
重新啟動應用程式 config-server
和 config-client
,再次訪問 http://localhost:8762/foo
,服務端的響應資料如下:
foo version 2
可見, config-server
從遠端 Git
倉庫讀取了 配置檔案 ,進一步 config-client
從 config-server
讀取了相關的 配置屬性 。
4. 構建高可用的Config Server
將 配置中心 config-server
做成一個 微服務 ,並且將其 叢集化 ,從而實現 高可用 。
4.1. 改造Config Server
在 Config Server
中引入 Eureka
客戶端的 起步依賴 spring-cloud-starter-eureka
。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> 複製程式碼
在應用的 啟動類 上加上 註解 @EnableEurekaClient
,將 Config Server
註冊到 Eureka Server
上面。
在配置檔案 application.yml
加入 服務註冊地址 :
eureka: client: service-url: defaultZone: http://locahost:8761/eureka/ 複製程式碼
4.2. 改造Config Client
同樣的在 Config Client
中引入 Eureka
客戶端的 起步依賴 spring-cloud-starter-eureka
。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> 複製程式碼
在應用的 啟動類 上加上 註解 @EnableEurekaClient
,將 Config Client
註冊到 Eureka Server
上面。
在配置檔案 application.yml
加入 服務註冊地址 :
eureka: client: service-url: defaultZone: http://locahost:8761/eureka/ 複製程式碼
在配置檔案 application.yml
加入相關配置,從 service-id
為 config-server
的 配置服務 讀取相關 配置檔案 。
spring: application: name: config-client cloud: config: fail-fast: true discovery: enabled: true service-id: config-server profiles: active: dev server: port: 8762 eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ 複製程式碼
重新啟動應用程式 config-server
和 config-client
,再次訪問 http://localhost:8762/foo
,服務端的響應資料如下:
foo version 2
只需要啟動多個 config-server
例項 ,即可搭建一個 高可用 的 config-server
叢集。
5. 使用Spring Cloud Bus重新整理配置
Spring Cloud Bus
將 分散式節點 通過輕量級的 訊息代理 連線起來。它可以用於 廣播配置檔案 的更改或者 服務之間 的通訊,也可以用於 監控 。在 分散式配置檔案 被更改後,可以通過 Spring Cloud Bus
通知各個微服務中的即時重新整理 本地配置 。
5.1. 改造config-client
在 config-client
的 pom.xml
裡面加入 起步依賴 spring-cloud-starter-bus-amqp
。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency> 複製程式碼
在專案的配置檔案 application.yml
檔案中新增 RabbitMQ
的相關配置,包括 RabbitMQ
的 地址 、 埠 、 使用者名稱 和 密碼 。為了方便驗證,將 management.security.enabled
改為 false
。
spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest management.security.enabled=false 複製程式碼
最後,在需要更新屬性的 配置類 上加 @RefreshScope
註解。
@RefreshScope @RestController @SpringBootApplication public class ConfigClientApplication { public static void main(String[] args) { SpringApplication.run(ConfigClientApplication.class, args); } @Value("${foo}") private String foo; @RequestMapping(value = "/foo") public String foo(){ return foo; } } 複製程式碼
依次啟動應用,啟動兩個 config-client
例項, 埠 分別為 8762
和 8763
。啟動完成後,訪問 http://localhost:8762/foo
或者 http://localhost:8763/foo
,服務端響應資料如下:
foo version 2
更改遠端 Git
倉庫 配置檔案 的 config-client-dev.properties
,將 foo
的值改為 “foo version 3”
。
訪問 http://localhost:8762/bus/refresh
請求 重新整理配置 ,設定 “destination”
引數為 待重新整理 屬性的 服務名稱 。例如 “http://localhost:8762/bus/refresh?destination=config-client:**”
,即 重新整理服務名 為 config-client
的所有 服務例項 。

再次訪問 http://localhost:8762/foo
和 http://localhost:8763/foo
,服務端響應資料如下:
foo version 3
測試結果表明, /bus/refresh
通知服務名為 config-client
的所有例項 重新整理 了本地的 foo
屬性配置。