SpringCloud10:Spring Cloud Config分散式配置
Spring Cloud Config為分散式系統中的外部配置提供伺服器和客戶端支援。使用Config Server,您可以在所有環境中管理應用程式的外部屬性。客戶端和伺服器上的概念對映與Spring Environment和PropertySource抽象相同,因此它們與Spring應用程式非常契合,但可以與任何以任何語言執行的應用程式一起使用。隨著應用程式通過從開發人員到測試和生產的部署流程,您可以管理這些環境之間的配置,並確定應用程式具有遷移時需要執行的一切。伺服器儲存後端的預設實現使用git,因此它輕鬆支援標籤版本的配置環境,以及可以訪問用於管理內容的各種工具。很容易新增替代實現,並使用Spring配置將其插入。
1、概述
1.1 分散式系統面臨的–配置檔案問題
微服務意味著要將單體應用中的業務拆分成一個個子服務,每個服務的粒度相對較小,因此係統中會出現大量的服務,由於每個服務都需要必要的配置資訊才能執行,所以一套集中式的,動態的配置管理設施是必不可少的。spring cloud提供了configServer來解決這個問題,我們每一個微服務自己帶著一個application.yml,那上百個的配置檔案修改起來,令人頭疼!
1.2 什麼是SpringCloud config分散式配置中心?
SpringCloud Config 為微服務架構中的微服務提供集中化的外部支援,配置伺服器為各個不同微服務應用的所有環節提供了一個中心化的外部配置
SpringCloud Config 分為服務端和客戶端兩部分。
服務端也稱為 分散式配置中心,它是一個獨立的微服務應用,用來連線配置伺服器併為客戶端提供獲取配置資訊,加密,解密資訊等訪問介面。
客戶端則是通過指定的配置中心來管理應用資源,以及與業務相關的配置內容,並在啟動的時候從配置中心獲取和載入配置資訊。配置伺服器預設採用git來儲存配置資訊,這樣就有助於對環境配置進行版本管理。並且可用通過git客戶端工具來方便的管理和訪問配置內容。
1.3 SpringCloud Config 分散式配置中心能幹嘛?
- 集中式管理配置檔案
- 不同環境,不同配置,動態化的配置更新,分環境部署,比如 /dev /test /prod /beta /release
- 執行期間動態調整配置,不再需要在每個服務部署的機器上編寫配置檔案,服務會向配置中心統一拉取配置自己的資訊
- 當配置發生變動時,服務不需要重啟,即可感知到配置的變化,並應用新的配置
- 將配置資訊以REST介面的形式暴露
1.4 SpringCloud Config 分散式配置中心與GitHub整合
由於SpringCloud Config 預設使用git來儲存配置檔案 (也有其他方式,比如自持SVN 和本地檔案),但是最推薦的還是git ,而且使用的是 http / https 訪問的形式。
2、入門案例
2.1 環境搭建
去gitee新建一個遠端配置中心倉庫
將遠端倉庫clone到本地,並新建application.yml檔案
填入以下內容,並上傳到遠端倉庫
更新到遠端倉庫
2.2 SpringCloud Config服務端實現
建立server模組:springcould-config-server-3344,匯入依賴
<dependencies>
<!--config-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
編寫配置檔案
#設定微服務執行埠
server:
port: 3344
#標識微服務名稱
spring:
application:
name: springcould-config-server
#連線遠端倉庫的配置
cloud:
config:
server:
git:
uri: https://gitee.com/ilovemo/springcloud-config.git
#直接去遠端倉庫上覆制地址,注意使用的是HTTPS,不再是使用git本地克隆的時候使用的SSH,原因就是正常分散式中微服務連線都是基於HTTP的
#注意是URI不是URL
編寫主啟動類,注意使用註解@EnableConfigServer 開啟config配置服務端
@SpringBootApplication
@EnableConfigServer //開啟config配置服務端
public class ConfigServer_3344 {
public static void main(String[] args) {
SpringApplication.run(ConfigServer_3344.class, args);
}
}
這裡直接啟動會報錯,需要加NativeEnvironmentRepository的Bean,再config包下新建ConfigBean.java配置類
@Configuration
public class ConfigBean {
@Bean
public NativeEnvironmentRepository
nativeEnvironmentRepository(NativeEnvironmentRepositoryFactory factory,
NativeEnvironmentProperties environmentProperties) {
return factory.build(environmentProperties);
}
}
測試
直接訪問application.yml報錯,這是因為我們準備了兩套環境,需要指定獲取哪套環境
官方文件指出,除了使用上面例子中的URL獲取到倉庫中配置檔案,還可以使用其他的形式獲取到配置檔案資源
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
可見不同的訪問URL得到的資料資源格式不一樣,資料也有一些不一樣
2.3 SpringCloud Config 客戶端實現
客戶端就是服務提供者對應的微服務模組,在spring cloud config中,客戶端需要從spring cloud config服務端獲取配置檔案的資訊
在本地倉庫中建立一個新的yml配置檔案,作為等會兒寫的服務提供者的遠端配置檔案
spring:
profiles:
active: dev
---
#埠配置
server:
prot: 8201
#spring配置
spring:
profiles: dev
application:
name: springcould-provider-dept
#eureka配置
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
---
#埠配置
server:
prot: 8202
#spring配置
spring:
profiles: test
application:
name: springcould-provider-dept
#eureka配置
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
推送到遠端倉庫
建立一個新的子model:springcould-config-client-3355,匯入依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
建立配置檔案,這裡我們需要學習一個新的配置檔案:bootstrap.yml,原來我們建立的都是application.yml,那麼這兩個配置檔案有什麼區別呢?
- bootstrap.yml:代表系統級別的配置
- application.yml:代表應用級別的配置
- 在原來學習反射的時候,我們學習了類載入器,其中有3個類載入器
- 根類載入器(bootstrap class loader)
- 擴充套件類載入器(extensions class loader)
- 系統類載入器(system class loader)
- 其中根載入器的優先級別最高
- 類比學習,bootstrap.yml配置檔案的優先順序應該比application.yml配置檔案的優先順序高
為什麼要搞一個系統配置檔案呢?原因就是application.yml中的配置可能和遠端倉庫中的配置衝突,就會造成配置不能正常的使用,而我們使用bootstrap.yml由於優先級別更高,那麼最終配置就會按照bootstrap.yml中的配置為準,可以防止本地和遠端倉庫中的配置衝突問題
在spring cloud config中,只有config伺服器模組才去連線遠端倉庫,而config客戶端只應該去連線config伺服器,所以config客戶端的config.uri屬性值應該是config服務端的地址(IP+埠)
spring:
cloud:
config:
uri: http://localhost:3344 #連線config服務端
config客戶端除了要配置config.uri之外,還需要配置自己需要載入遠端倉庫中的哪一個配置檔案,按照剛剛直接通過config伺服器獲取配置檔案的URL,我們需要配置name(配置檔名稱)、profile(這個配置檔案中的哪一個環境下的配置)、label(配置檔案所在分支)、uri(config服務端的地址[IP+埠])
# 系統級別的配置
spring:
cloud:
config:
name: config-client # 需要從git上讀取的資源名稱,不要字尾
profile: test
label: master
uri: http://localhost:3344
編寫入口程式
@SpringBootApplication
public class ConfigClient_3355 {
public static void main(String[] args) {
SpringApplication.run(ConfigClient_3355.class,args);
}
}
注意:入口程式並不需要加什麼註解,按照正常的spring boot的入口程式寫就行了
編寫一個controller,用來檢測config客戶端模組是不是能夠讀取遠端的配置檔案並作為自己模組配置檔案的一部分進行使用
@RestController
public class ConfigController {
@Value("${spring.application.name}")
private String applicationName;
@Value("${eureka.client.service-url.defaultZone}")
private String eurekaServer;
@Value("${server.port}")
private String serverPort;
@RequestMapping("/getConfig")
public String getConfig() {
return "applicationName = " + this.applicationName + "\n" +
"eurekaServer = " + this.eurekaServer + "\n" +
"serverPort = " + this.serverPort;
}
}
在上面的controller中,我們使用了註解@Value,用於直接向成員屬性中注入指定的值,我們又使用了${ }來解析一些的遠端配置檔案中才配置了的一些配置變數的值,最後通過controller的一個API向外提供輸出服務,我們可以直接訪問這個API,來檢驗config客戶端是不是讀取到了遠端倉庫中指定配置檔案的內容