1. SpringCloud Config概述
1.1 分布式系統面臨的配置問題
微服務意味着要将單體應用中的業務拆分成一個一個子服務,每個服務的粒度相對較小,是以系統中會出現大量的服務。由于每個服務都需要必要的配置才能運作,是以一套集中式的,動态的配置管理設施是必不可少的。
SpringCloud提供了Config Server來解決這個問題,否則我們每一個微服務自己帶着一個application.yml,上百個配置檔案的管理會令人頭疼。
1.2 是什麼
如圖,服務配置中心從遠端讀取配置檔案,然後用戶端服務再通過服務配置中心讀取配置。
SpringCloud Config為微服務架構中的微服務提供集中化的外部配置支援,配置伺服器為 各個不同微服務應用 的所有環境提供了一個 中心化的外部配置 。
SpringCloud Config分為服務端和用戶端兩部分:
- 服務端也稱為 分布式配置中心,它是一個獨立的微服務應用 ,用來連接配接配置伺服器并為用戶端提供擷取配置資訊,加密/解密資訊等通路接口,将配置資訊以REST接口的形式暴露給用戶端(用戶端可以用REST風格方式讀取到該配置資訊)。
- 用戶端則是通過指定的配置中心來管理應用資源,以及與業務相關的配置内容,并在啟動的時候從配置中心擷取和加載配置資訊。配置伺服器預設采用git來存儲配置資訊,這樣就有助于對環境配置進行版本管理,并且可以通過git用戶端工具來友善的管理和通路配置内容。
1.3 作用
- 集中管理配置檔案
- 不同環境不同配置,動态化的配置更新,分環境比如dev/test/prod/beta/release
- 運作期間動态調整配置,不再需要在每個服務部署的機器上編寫配置檔案,服務會向配置中心同意拉取配置自己的資訊
- 當配置發生改變時,服務不需要重新開機即可感覺到配置的變化并應用新的配置
- 将配置資訊以REST接口的形式暴露 (post/crul通路重新整理即可)
1.4 與GitHub整合配置
由于SpringCloud Config預設使用Git來存儲配置檔案(也有其他方式,比如支援SVN和本地檔案),但最推薦還是Git,而且使用的是http/https的通路形式。
2. Config 服務端配置與測試
2.1 Gitee倉庫
在Gitee上建立一個用作配置中心的新倉庫,并克隆到本地開發硬碟目錄
然後根據建立的Git位址,将Gitee上的倉庫克隆到本地
git clone https://gitee.com/mp2333/springcloud-config.git
2.2 建Module
建立Module:cloud-config-center-3344作為配置中心微服務
在其POM檔案中引入服務配置中心的依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
修改其配置檔案application.yml如下:
server:
port: 3344
spring:
application:
name: cloud-config-center # 注冊進Eureka伺服器的微服務名
cloud:
config:
server:
git:
uri: https://gitee.com/mp2333/springcloud-config.git # GitHub上面的git倉庫名字
# 搜尋目錄
search-paths:
- springcloud-config
# 注意:如果倉庫私有則需要添加username/password
# 讀取分支
label: master
# 服務注冊到eureka位址
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka
編寫主啟動類,在主啟動類上添加注解
@EnableConfigServer
使3344微服務具有配置中心功能:
@SpringBootApplication
@EnableConfigServer
public class ConfigCenterMain3344 {
public static void main(String[] args) {
SpringApplication.run(ConfigCenterMain3344.class);
}
}
修改hosts檔案,增加映射,使本機模拟網址服務配置中心網址:
127.0.0.1 config-3344.com
2.3 GitHub倉庫建配置檔案
如圖,就是建立了一個簡單的配置檔案,用來測試能否通過配置中心微服務擷取内容。
2.4 測試
配置讀取規則 (五種)
- /{label}/{application}-{profile}.yml
# master分支
http://config-3344.com:3344/master/config-dev.yml
http://config-3344.com:3344/master/config-prod.yml
# dev分支
http://config-3344.com:3344/dev/config-dev.yml
http://config-3344.com:3344/dev/config-prod.yml
- /{application}-{profile}.yml 預設master分支
http://config-3344.com:3344/config-dev.yml
http://config-3344.com:3344/config-prod.yml
- /{application}/{profile}[/{label}]
# master分支
http://config-3344.com:3344/config/dev/master
http://config-3344.com:3344/config/prod/master
# dev分支
http://config-3344.com:3344/config/dev/dev
http://config-3344.com:3344/config/prod/dev
先啟動Eureka服務注冊中心,然後啟動服務配置中心微服務3344,通路 http://config-3344.com:3344/master/config-dev.yml ,我們可以看到3344微服務可以成功的讀取到遠端的配置檔案。
是以現在,服務配置中心從遠端Git倉庫讀取配置檔案這一部分已經搭建完成:
3. Config 用戶端配置與測試
3.1 建Moudle
建立Module:cloud-config-client-3355作為通路配置中心的用戶端
在其POM檔案中引入Config配置中心用戶端的啟動類:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
3.2 編寫配置檔案bootstrap.yml
application.yml
是使用者級的資源配置項,而
bootstrap.yml
是系統級的資源配置項,
bootstrap.yml
的優先級更高,SpringCloud會建立一個"Bootstrap Context",作為Spring應用的“Application Context"的 父上下文。初始化的時候,“Bootstrap Context"負責從外部源加載配置屬性并解析配置,這兩個上下文共享一個從外部擷取的"Environment”。”Bootstrap“屬性有高優先級,預設情況系,它們不會被本地配置覆寫。"Bootstrap Context"和"Application Context"這兩個上下文有不同的約定,是以新增一個
bootstrap.yml
檔案,保證這兩個上下文的配置分離。
是以,要将Client子產品下的application.yml檔案改為bootstrap.yml,這是很關鍵的,因為bootstrap.yml是比application.yml先加載的。編寫bootstrap配置檔案如下:
server:
port: 3355
spring:
application:
name: config-client
cloud:
# Config用戶端配置
config:
label: master # 分支名稱
name: config # 配置檔案名稱
profile: dev # 讀取字尾名稱
# 上述3個綜合:master分支上config-dev.yml的配置檔案被讀取
uri: http://localhost:3344 # 配置中心位址
# http://config-3344.com:3344/master/config-dev.yml
# 服務注冊到eureka位址
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka
編寫3355服務的主啟動類,之後編寫其業務類:
@RestController
public class ConfigClientController {
@Value("${server.info}") //配置中心config-dev.yml配置的内容
private String configInfo;
@GetMapping("/configInfo")
public String getConfigInfo() {
return configInfo;
}
}
3.3 測試
下面測試用戶端是否能夠通過通路配置中心擷取配置資訊
按順序啟動Eureka服務注冊中心,Config服務配置中心後,啟動我們的服務配置中心用戶端3355進行測試:
3.4 存在的問題
我們在GitHub上修改配置檔案内容,重新整理3344配置中心服務端,發現Config Server配置中心立刻響應并重新整理了配置資訊,但是!我們重新整理3355用戶端Config Client,發現沒有任何響應,配置資訊仍然是原來的配置資訊。
難道每次遠端修改了配置檔案後,用戶端都需要重新開機來進行對配置資訊的重新加載嗎?
4. Config 用戶端之動态重新整理
為了避免每次遠端更新配置資訊都需要重新開機用戶端微服務3355來加載更新的配置資訊,我們需要使用動态重新整理。
4.1 修改3355子產品
在POM中引入actuator監控:
其實actuator依賴幾乎處了是網關的微服務外都得加。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
4.2 修改配置檔案
在
bootstrap.yml
中加入如下配置 暴露監控端點:
# 暴露監控端點
management:
endpoints:
web:
exposure:
include: "*"
4.3 @RefreshScope注解
在業務類Controller上添加
@RefreshScope
注解使用戶端服務具有重新整理功能:
@RestController
@RefreshScope
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/configInfo")
public String getConfigInfo() {
return configInfo;
}
}
4.4 發送Post請求重新整理用戶端3355
該重新整理請求必須發送後,用戶端才能獲得重新整理後的資訊,重新整理用戶端的請求必須是POST請求:
curl -X POST "http://127.0.0.1:3355/actuator/refresh"
當出現以上資訊時激活重新整理用戶端3355成功,再次通路用戶端,發現已經可以得到重新整理後的配置資訊。
但是假設如果我們有多個微服務用戶端呢?難道每個微服務都需要執行一次POST請求進行手動重新整理嗎?事實上我們可以通過廣播的方式進行一次通知,處處生效,這裡就要知道消息總線 => SpringCloud Bus。