在 分佈式系統 中,因爲服務數量巨多,爲了方便 服務配置文件 的 統一管理 和 實時更新,因此須要 分佈式配置中心 組件。 Spring Cloud
提供的 分佈式配置中心 組件是 Spring Cloud Config
,它支持將 配置服務 放在配置服務的 內存 中(即 本地),也支持放在 遠程 Git
倉庫中。Spring Cloud Config
提供了兩個角色,一個是 Config Server
,二個是 Config Client
。
建立一個新的 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
應用程序。
建立一個 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
變量。
修改 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: ostenant@163.com
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
讀取了相關的 配置屬性。
將 配置中心 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/
複製代碼
一樣的在 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
集羣。
Spring Cloud Bus
將 分佈式節點 經過輕量級的 消息代理 鏈接起來。它能夠用於 廣播配置文件 的更改或者 服務之間 的通信,也能夠用於 監控。在 分佈式配置文件 被更改後,能夠經過 Spring Cloud Bus
通知各個微服務中的即時刷新 本地配置。
在 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
屬性配置。
歡迎關注技術公衆號: 零壹技術棧
本賬號將持續分享後端技術乾貨,包括虛擬機基礎,多線程編程,高性能框架,異步、緩存和消息中間件,分佈式和微服務,架構學習和進階等學習資料和文章。