書接上回:
隨著服務越來越多,部署的叢集越來越多,如果需要改某一個配置資訊,那需要改動程式碼,列印成jar包,然後服務上線。這樣維護的代價也太大了吧。這個時候就需要一個分散式的配置中心的元件了,實現程式碼和配置檔案的解耦。
Spring Cloud Config主要為分散式系統中的基礎設施合微服務應用提供集中化的外部配置支援。分為服務端喝客戶端兩個部分。其中服務端也稱為分散式配置中心,用來連線配置倉庫併為客戶端提供獲取配置資訊、加密/解密資訊等訪問介面。客戶端主要是微服務架構中的各個微服務應用或基礎設施,通過指定的配置中心來管理應用資源與業務相關的配置內容,並在啟動的時候從配置中心獲取和載入配置配置資訊。
Spring Cloud Config實現的配置中心預設採用Git來儲存配置資訊,當然它也提供了對其他儲存方式的支援,比如SVN倉庫,本地化檔案系統。
構建配置中心(config-server)
config-server的功能是:處理config client的請求,並訪問Git,實現配置檔案的餓查詢,下載後在本地快取,並將下載的配置傳送到config client。
1.引入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
2.開啟Spring Cloud Config的服務端功能
/**
* EnableConfigServer:
* 開啟spring cloud 中的config伺服器,自動提供config伺服器相關的功能,
* 啟動時,同步啟動taomcat,埠預設為8888,
* 一般配置中心伺服器的埠定義為8888,因為config客戶端預設查詢的config伺服器的地址是:
* http://localhost:8888/
*/
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
3.配置服務的相關資訊
spring.application.name=config-server
server.port=8888
# 配置git的位置(建議大家用gitee測試,git在測試的過程中連不上是真的煩)
spring.cloud.config.server.git.uri=https://gitee.com/charon1798766775/spring_cloud_config_repo.git
# 配置倉庫路徑下的相對搜尋位置,可以配置多個
#spring.cloud.config.server.git.search-paths=XXXXX
# 如果是私有倉庫,需要設定訪問git的使用者名稱
#spring.cloud.config.server.git.username=XXXXX
# 如果是私有倉庫,需要設定訪問git的密碼
#spring.cloud.config.server.git.password=XXXXX
這裡我在git上建立了4個分支(master、env、test、prod),根據不同的環境建立不同的配置檔案:
-
config.properties
my.config.server.name=charon
my.config.server.age=20
my.config.server.env=default
-
config-dev.properties
my.config.server.name=charon_dev
my.config.server.age=20
my.config.server.env=dev
-
config-test.properties
my.config.server.name=charon_test
my.config.server.age=20
my.config.server.env=test
-
config-prod.properties
my.config.server.name=charon_prod
my.config.server.age=20
my.config.server.env=prod
根據上面的對映檔案,我們在可以直接通過restful api的方式進行訪問配置,具體的路由規則如下:
- /{application}/{profile}[/{label}]
- /{application}-{profile}.yml
- /{label}/{application}-{profile}.yml
- /{application}-{profile}.properties
- /{label}/{application}-{profile}.properties
其中{label}對應的是Git上不同的分支,預設為master。比如我們需要訪問test分支的內容,那麼應該訪問的url為:http://localhost:8888/config/test/test 。
三層訪問規則:
- config:配置檔案的名稱
- test:配置檔案的profiles,預設的為default
- test:分支名稱
從上面返回的json中的內容可以看到有個version欄位,它就是在git上的commit號。
config-server在從git上獲取配置資訊後,會儲存一份在config-server的檔案系統中,也就是config-server是通過git clone命令將配置內容複製了一份在本地儲存,然後讀取這些內容並返回給微服務應用進行載入。
config-server通過在本地暫存一份,可以防止GIt倉庫出現故障而引起午發載入配置資訊的情況。
客戶端配置對映
下面我們嘗試用服務獲取配置資訊。
1.引入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
2.controller類
/**
* @className: ConfigClientController
* @description: 控制器
* @author: charon
* @create: 2021-07-31 16:18
*/
@RestController
public class ConfigClientController {
/**
* 配置檔案中的name
*/
@Value("${my.config.server.name}")
private String name;
/**
* 配置檔案中的age
*/
@Value("${my.config.server.age}")
private String age;
/**
* 配置檔案中的env
*/
@Value("${my.config.server.env}")
private String env;
@GetMapping("/getConfig")
public String getConfig() {
return "返回配置檔案中的資料:name=" + name + ";age=" + age + ";env=" + env;
}
}
3.配置檔案
在這裡使用bootstrap.properties配置檔案作為配置中心。因為在spring boot啟動時,bootstrap的配置檔案是第一個載入的,優先順序最高,然後才載入application的配置檔案,最後載入application-profiles的配置檔案。
spring.application.name=config-client
server.port=9011
# 需要配置spring cloud config server位置和要載入的相關引數
# spring cloud config server的連線地址
spring.cloud.config.uri=http://localhost:8888
# 要載入的配置檔案主體命名
spring.cloud.config.name=config
# 要載入的配置檔案所在的分支命名,預設為null,相當於master
spring.cloud.config.label=master
# 要載入的配置檔案的profile,預設為default
spring.cloud.config.profile=default
獲取配置的引數
這樣是可以獲取到配置中心的引數了,但是還有一個問題,就是如果配置檔案發生了變更,服務還需要重啟才能生效,那接下來就處理熱重新整理的問題。
熱重新整理
1.引入監控包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2.配置檔案
將相關管理以及健康管理埠暴露,spring boot2.0和spring boot1.0區別還挺大的
management.server.port=9012
management.endpoints.enabled-by-default=true
management.endpoints.web.base-path=/
management.endpoints.web.exposure.include=info,health,refresh
3.在controller類上,新增@RefreshScope註解,
@RefreshScope的作用:通知spring容器,熱重新整理的時候,重新重新整理當前型別對應的所有物件,spring容器為提升熱重新整理效率,預設不重新整理物件內容,只有明確指定的物件,才重新整理。
4.將配置檔案的my.config.server.age修改為50。
5.用postman傳送post請求。
6.驗證
config server除了使用git倉庫外,還可以使用SVN倉庫或者本地倉庫做配置檔案。
服務化配置中心
在Spring Cloud中,可以把config server視為微服務架構中與其他業務服務一樣的一個基本單元。將config server註冊到服務中心,並通過服務發現來訪問config server並獲取Git倉庫中的配置資訊。
在服務端和客戶端分別加上eureka的依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
配置eureka的地址
# 配置服務註冊中心
eureka.client.serviceUrl.defaultZone=http://eureka-server1:9001/eureka/
在應用主類中,新增@EnableDiscoveryClient註解,用來將服務註冊到上面配置的服務註冊中心上去。
加密/解密
在實際專案中,往往存在大量的敏感資訊,比如資料庫賬號與密碼等一些資訊。顯然,如果直接以明文的方式儲存在配置檔案中是非常危險的。針對這一問題,Spring Cloud Config提供了對屬性加密與解密的功能,以保護配置檔案中的資訊保安。
在Spring Cloud Config中通過在屬性值前使用{cipher}字首來標記該內容是一個加密值,當微服務客戶端載入配置時,配置中心會自動為帶有{cipher}字首的值進行解密。通過這種機制,就可以不用擔心敏感資訊遭到洩露了。
1.使用前提
Java 中提供了一套用於實現加密、金鑰生成等功能的包 JCE(Java Cryptography Extension),這些包提供了對稱、非對稱、塊和流密碼的加密支援,但是預設的 JCE 是一個有限長度的 JCE ,我們需要到 Oracle 官網去下載一個不限長度的 JCE :
jdk1.8不限長度JCE下載地址
下載完成後,將下載檔案解壓,解壓後的檔案包含如下三個檔案:
將 local_policy.jar 和 US_export_policy.jar 兩個檔案拷貝到 JDK 的安裝目錄下,具體位置是 %JAVA_HOME%\jre\lib\security
,如果該目錄下有同名檔案,則直接覆蓋即可。
2.配置金鑰
我們可以通過encrypt.key屬性在配置檔案中直接指定金鑰資訊(對稱性金鑰),比如:
# 配置金鑰
encrypt.key=666666
加入上面的配置資訊後,重啟配置中心,再訪問localhost:8888/encrypt/status,可以看到有返回{"status":"OK"}
的內容。此時配置中心的加密解密功能就已經可以正常使用了。可以使用/encrypt和/decrypt來使用加密和解密功能了(post請求)。
加密:
解密:
下面我們在遠端配置檔案中的my.config.server.name的配置資訊改為如下:
my.config.server.name={cipher}508d0eda835b6de26dcff97b75baf787c11d5cef5066999d1564af0d7f35e574
注意{cipher}不要忘記了,只有加上它才能解密。
在這裡,我們通過配置encrypt.key引數來指定金鑰的實現方式為對稱性金鑰。Spring Cloud Config的配置中心不僅可以使用對稱性加密,也可以使用非對稱性加密。
參考文章:
翟永超老師的《Spring Cloud微服務實戰》
https://www.bilibili.com/video/BV1xV411e79Z?p=5&spm_id_from=pageDriver