相關
前言
在 分散式系統 中,由於服務數量巨多,為了方便 服務配置檔案 的 統一管理 和 實時更新,所以需要 分散式配置中心 元件。 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: 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
讀取了相關的 配置屬性。
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
屬性配置。
參考
- 方誌朋《深入理解Spring Cloud與微服務構建》
歡迎關注技術公眾號: 零壹技術棧
本帳號將持續分享後端技術乾貨,包括虛擬機器基礎,多執行緒程式設計,高效能框架,非同步、快取和訊息中介軟體,分散式和微服務,架構學習和進階等學習資料和文章。