七. SpringCloud服務配置
- 2021 年 3 月 4 日
- 筆記
- SpringCloud, 微服務
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 //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: //gitee.com/mp2333/springcloud-config.git # GitHub上面的git倉庫名字
# 搜索目錄
search-paths:
- springcloud-config
# 注意:如果倉庫私有則需要添加username/password
# 讀取分支
label: master
# 服務註冊到eureka地址
eureka:
client:
service-url:
defaultZone: //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分支
//config-3344.com:3344/master/config-dev.yml
//config-3344.com:3344/master/config-prod.yml
# dev分支
//config-3344.com:3344/dev/config-dev.yml
//config-3344.com:3344/dev/config-prod.yml
- /{application}-{profile}.yml 默認master分支
//config-3344.com:3344/config-dev.yml
//config-3344.com:3344/config-prod.yml
- /{application}/{profile}[/{label}]
# master分支
//config-3344.com:3344/config/dev/master
//config-3344.com:3344/config/prod/master
# dev分支
//config-3344.com:3344/config/dev/dev
//config-3344.com:3344/config/prod/dev
先啟動Eureka服務註冊中心,然後啟動服務配置中心微服務3344,訪問 //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: //localhost:3344 # 配置中心地址
# //config-3344.com:3344/master/config-dev.yml
# 服務註冊到eureka地址
eureka:
client:
service-url:
defaultZone: //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 "//127.0.0.1:3355/actuator/refresh"
當出現以上資訊時激活刷新客戶端3355成功,再次訪問客戶端,發現已經可以得到刷新後的配置資訊。
但是假設如果我們有多個微服務客戶端呢?難道每個微服務都需要執行一次POST請求進行手動刷新嗎?事實上我們可以通過廣播的方式進行一次通知,處處生效,這裡就要知道消息匯流排 => SpringCloud Bus。