書接上回:
隨着服務越來越多,部署的集群越來越多,如果需要改某一個配置信息,那需要改動代碼,打印成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
