概述
分布式系統面臨的問題
微服務意味着要將單體應用中的業務拆分成一個個的子服務,這些服務都需要必要的配置信息才能運行,如果有上百個微服務,上百個配置文件,管理起來是非常困難的,這時候,一套集中式的、動態的配置管理中心是必不可少的,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 消息總線