概述
分散式系統面臨的問題
微服務意味著要將單體應用中的業務拆分成一個個的子服務,這些服務都需要必要的配置資訊才能執行,如果有上百個微服務,上百個配置檔案,管理起來是非常困難的,這時候,一套集中式的、動態的配置管理中心是必不可少的,Spring Cloud 提供了 ConfigServer 來解決這個問題。
是什麼?
Spring Cloud Config 為微服務提供了集中化的外部配置支援,配置伺服器為不同微服務應用的所有環境提供了一箇中心化的外部配置。
Spring Cloud Config 分為服務端和客戶端兩部分。
- 服務端也成為分散式配置中心,它是一個獨立的微服務應用,用來連線配置伺服器,併為客戶端提供獲取配置資訊、加密解密資訊燈訪問介面
- 客戶端則是通過指定的配置中心來管理應用資源以及與業務相關的配置內容,並在啟動的時候從配置中心獲取和載入配置資訊,配置伺服器預設使用 git 來儲存配置資訊,這樣就有助於對環境配置進行版本管理,並且可以通過 git 客戶端工具來方便的管理和訪問配置內容
能幹嘛?
- 集中管理配置檔案
- 不同環境不同配置,動態化的配置更新,分環境部署,比如dev/prod/test/beta/release
- 執行期間動態調整配置,不再需要在每個服務上編寫配置檔案,服務會向配置中心統一拉取自己的配置
- 當配置發生變動時,服務無需重啟,可以動態的應用新配置
- 將配置資訊以 REST 介面的形式暴露給微服務
與 Github 整合配置
Spring Cloud Config 預設使用 Git 來儲存配置檔案(也有其他方式,比如SVN、本地檔案,但最推薦的還是 Git),而且使用的是 http/https 訪問的形式
基本使用
服務端準備
1、使用 GitHub 或其它程式碼庫建立一個倉庫 springcloud-config
,新增幾個檔案,建立一個 dev 分支
2、新建一個專案當作配置中心,新增 maven 依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3、在application.yml
新增如下配置,配置自己的遠端倉庫地址,如果 ssh 無法連線可以嘗試使用 https
server:
port: 3344
spring:
application:
name: cloud-config-center
cloud:
config:
server:
git:
# 遠端庫地址
uri: @*&%$%#$%
# 搜尋目錄
search-paths:
- springcloud-config
# 讀取分支
label: master
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka
4、在主啟動類上開啟配置服務
@SpringBootApplication
@EnableConfigServer
public class ConfigCenterMain3344 {
public static void main(String[] args){
SpringApplication.run(ConfigCenterMain3344.class, args);
}
}
5、在瀏覽器輸入如下地址可以訪問到配置檔案的資訊
官網上介紹瞭如下幾種訪問方式:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
其中第一種方式返回的是 json 資料(如下圖所示),其它方式返回的都是檔案真正的內容
客戶端準備
我們使用 bootstrap.yml 最為配置檔案
application.yml 是使用者級的資源配置項
bootstrap.yml 是系統級的,優先順序更高
Spring Cloud 會建立一個 Bootstrap Context,作為 Spring 應用的 Application Context 的父上下文。初始化的時候,Bootstrap Context 負責從外部源載入配置屬性,並解析配置。這兩個上下文共享一個從外部獲取的 Environment。
Bootstrap 屬性有高優先順序,預設情況下,它們不會被本地配置覆蓋,Bootstrap Context 和 Application Context 有著不同的約定,所以新加一個 bootstrap.yml 檔案,保證 Bootstrap Context 和 Application Context 配置的分離
1、新增 Maven 依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2、新增配置檔案 bootstrap.yml
server:
port: 3355
spring:
application:
name: cloud-config-client
cloud:
config:
label: master #分支名
name: config #配置檔名
profile: test #配置檔案字尾
uri: http://config3344.com:3344
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka
3、編寫 controller,獲取配置中心中的檔案屬性
@RestController
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/info")
public String getConfigInfo(){
return configInfo;
}
}
4、瀏覽器輸入地址訪問
如果需要獲取其它配置檔案內容,只需要修改 bootstrap.yml
中的 label
、name
、profile
即可
存在的問題?
當配置中心的配置檔案內容發生改動,服務端和客戶端是否能夠動態的獲取?
經測試,服務端可以動態的獲取,客戶端不能!
因為服務端直接從配置中心獲取,而客戶端是從上下文環境中獲取已載入的屬性,配置中心修改後,由於服務沒有重啟,獲取的仍然是之前的屬性。
Config 動態重新整理
對客戶端進行修改
1、需要引入 actuator 依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、新增如下配置
# 暴露監控端點
management:
endpoints:
web:
exposure:
include: "*"
3、在 Controller 上新增註解 @RefreshScope
4、重新整理服務端後,傳送 Post 請求,curl -X POST http://localhost:3355/actuator/refresh
,客戶端重新整理即可獲取最新內容,避免了服務重啟
仍然存在的問題?
- 每個微服務都需要傳送一次 POST 請求。
- 如何廣播通知?一次通知,處處生效
- 如何進行差異化的處理,讓部分服務動態獲取
下一篇為大家介紹:Spring Cloud Bus 訊息匯流排