目錄
1、簡介
2、正文
2.1 Spring Cloud Config + 手動重繪
2.2 Spring Cloud Config + Git + WebHook實作自動重繪
2.3 Spring Cloud Config + Eureka
2.4 Spring Cloud Bus多端重繪
1、簡介
傳統配置的痛點:
- 在以前的專案中,我們通過組態檔、作業系統變數、Java系統屬性等方式配置Java專案;在spring boot爆火之后我們的配置資訊都寫在application.yml或application.properties檔案中,這些組態檔隨著專案的打包與應用一起發布;但是當我們需要修改組態檔中的配置資訊的時候,需要更新組態檔重新構建、重新發布;如果配置資訊配置在作業系統環境變數或者Java系統屬性中則需要重啟應用,
- 組態檔中往往有一些敏感資訊,比如資料庫密碼、Redis密碼、加密秘鑰等資訊,這些資訊如果直接配置在組態檔中,容易泄露,
針對這些問題,Spring Cloud早期發布了Spring Cloud Config進行集中式配置管理,成功解決了這些問題,
Spring Cloud Config分為Server端和Client端,其中Spring Cloud Config Server是Spring Cloud為指定應用中所有服務提供集中式配置的一個服務,借助Spring Cloud Config Server可以實作集中管理所有應用的配置,避免重復配置,
Spring Cloud Config帶來了諸多好處:
- 組態檔與應用解耦,可以在不重啟應用的前提下隨時更新發布、回滾組態檔
- 不同的服務可以共享配置,這在微服務架構系統中非常有用,避免重復配置,大大降低了微服務配置的維護成本
- 配置與應用隔離之后,敏感資訊得到保護
Spring Cloud Config Server通過Git倉庫給微服務提供配置屬性架構圖:

2、正文
正文通過Spring Boot專案展開對Spring Cloud Config的探討,分別會有以下幾個方面來展開:
- Spring Cloud Config + Git手動重繪
- Spring Cloud Config + Git + WebHook實作自動重繪
- Spring Cloud Config + Eureka
- Spring Cloud Bus多端重繪
注意整個專案的搭建是一步一步來的,重復的步驟不會重復出現,
2.1 Spring Cloud Config + 手動重繪
Spring Cloud Config Server
首先需要搭建Spring Cloud Config Server服務,Spring Cloud Config Server服務應該作為一個單獨的應用運行和維護,所以我們單獨為Spring Cloud Config Server啟動一個服務,
依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
我這里選擇的Spring Boot版本和Spring Cloud版本如下(版本如果不對應會出現例外,大家可以選擇自己需要的對應版本):
<!--spring boot 版本 2.3.4.RELEASE-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<!--spring cloud 版本 Hoxton.RELEASE-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>>Hoxton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
application.yml組態檔:
下面的組態檔中有幾個點比較重要,配置錯誤將無法獲取配置資訊
a、default-label,組態檔所在分支,默認值為master

b、search-paths,組態檔所在根目錄

c、uri ,倉庫地址

## 服務名
spring:
application:
name: config-service
## config git相關配置
cloud:
config:
server:
git:
uri: https://gitee.com/leonplious/config-server-demo.git # 倉庫地址
username: xxxx # git 登錄賬戶
password: xxxx # git 登錄密碼
default-label: master # 分支
search-paths: userservice # 分支下根檔案夾名
## 服務埠
server:
port: 28888
撰寫啟動類,啟動類上需要添加@EnableConfigServer注解
@SpringBootApplication
@EnableConfigServer
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
此時我們可以開始測驗Spring Cloud Config Server,推送一個組態檔到git倉庫中,組態檔的名稱為userservice-dev.yml,組態檔的內容如下:
user:
username: "liziba"
password: "hello"
啟動Spring Cloud Config Server應用,訪問http://localhost:28888/userservice/dev/master,可以得到如下資訊,證明Spring Cloud Config Server服務啟動成功,
{
"name":"userservice",
"profiles":[
"dev"
],
"label":"master",
"version":"285fd1b9f068cec6def6ba14ab787807a9ffecbc",
"state":null,
"propertySources":[
{
"name":"https://gitee.com/leonplious/config-server-demo.git/userservice/userservice-dev.yml",
"source":{
"user.username":"liziba",
"user.password":"hello"
}
}
]
}
注意Spring Cloud Config 有它的一套訪問規則,通過這套規則可以獲取相應資料,資料的回應格式略有不同,
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
- application指應用名稱,我們的組態檔名稱應該嚴格按照application-{profile}.yml命名,
- profile指環境資訊,比如生產環境【prod】、開發環境【dev】、測驗環境【test】
- label指git分支,比如master
我這里使用的是第一種方式,這種方式能夠回傳詳細的配置資訊,以及分支資訊、profile資訊、應用名等,默認的分支名master可以省略,http://localhost:28888/userservice/dev等同于http://localhost:28888/userservice/dev/master
?
接下來就可以開始配置Spring Cloud Config Client
新建Spring Cloud Config Client服務,該服務會從Spring Cloud Config Server中獲取配置資訊,
依賴:
<!--config客戶端依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!--web提供rest訪問端點-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--actuator提供端點觸發更新-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
組態檔bootstrap.yml:
需要注意使用config獲取配置資訊時,我們需要將config相關配置提取到優先級最高的bootstrap.yml組態檔中,否則不會生效,spring-cloud-starter-config默認會訪問8888埠,如果你的Spring Cloud Config Server并未使用該埠啟動,可以在bootstrap.yml檔案中指定Spring Cloud Config Server埠資訊,這樣才能覆寫,否則獲取不到Spring Cloud Config Server上的配置資訊,
我這里的組態檔演示了多環境dev和prod,注意我的config.uri地址時http://localhost:28888,并不是http://localhost:8888
server:
port: 18888
spring:
application:
name: userservice
profiles:
active: dev
## 加載并暴露所有端點,用于或許重繪端點
management:
endpoints:
refresh:
enabled: true
web:
exposure:
include: '*'
## 配置中心無法訪問,回傳此資料
user:
username: NaN
password: NaN
---
spring:
profiles: dev
cloud:
config:
uri: http://localhost:28888
label: master
profile: dev
fail-fast: true
---
spring:
profiles: prod
cloud:
config:
uri: http://localhost:28888
label: master
profile: prod
fail-fast: true
撰寫兩個User和User2用于獲取配置資訊,兩個類獲取配置的方式不一樣,分別通過 @Value 或和**@ConfigurationProperties **來獲取:
@Data
@ToString
@Component
public class User {
@Value("${user.username}")
private String username;
@Value("${user.password}")
private String password;
}
@Data
@ToString
@Component
@ConfigurationProperties(prefix = "user")
public class User2 {
private String username;
private String password;
}
撰寫rest訪問端點,獲取兩個User的配置資訊:
@RequiredArgsConstructor
@RestController
@RequestMapping("/user")
public class UserController {
private final User user;
private final User2 user2;
@GetMapping("/user1")
public String user() {
return user.toString();
}
@GetMapping("/user2")
public String user2() {
return user2.toString();
}
}
啟動服務,分別訪問兩個rest端點,此時可以分別獲取到如下資訊,說明我們配置資訊已經獲取到了,
http://localhost:18888/user/user1
User(username=liziba, password=hello)
http://localhost:18888/user/user2
User2(username=liziba, password=hello)
此時我們將username修改成中文‘李子捌’,并推送到Gitee;修改后的組態檔如下:
user: username: "李子捌" password: "hello"
再次訪問兩個rest端點,發現兩個請求回傳的都是舊資料,并沒有獲取到最新的配置,別慌,沒人通知他更新它肯定是舊資料呀!這個時候我們引入的actuator依賴和management.endpoints配置就派上用場了,
我們可以借助postman、curl等http工具向http://localhost:18888/actuator/refresh端點發起post請求,

image.png
再次訪問兩個rest端點,分別回傳如下資料
http://localhost:18888/user/user1
User(username=liziba, password=hello)
http://localhost:18888/user/user2
User2(username=李子捌, password=hello)
@Value 獲取配置資訊的方式并未獲取到最新資料,而**@ConfigurationProperties **獲取配置資訊獲取到了更新后的資料,所以我們在開發的時候記得使用@ConfigurationProperties來結合config獲取配置資訊,
?
2.2 Spring Cloud Config + Git + WebHook實作自動重繪
實作自動重繪的功能,我們需要借助兩個東西;第一個是GitHub、Gitee、GitLab提供的WebHook功能,第二個是@RefreshScope注解,
第一步:配置WebHook(我這里采用的是Gitee)
進入你的組態檔所在倉庫地址,選擇管理頁簽之后選擇WebHooks,點擊添加WebHook

注意URL中填寫的是actuator提供的refresh端點,也就是我們上面用postman請求的地址,你可以選擇你需要觸發呼叫該地址的事件,一般選擇Push,特別需要注意的是,你是要Gitee或GitHub需要提供一個公網地址,一般公司內部都會搭建GitLab代碼倉庫,公司內部可以使用內網地址,
?
第二步:添加@RefreshScope注解
@RequiredArgsConstructor
@RestController
@RequestMapping("/user")
@RefreshScope
public class UserController {
// ...
}
?
2.3 Spring Cloud Config + Eureka
大部分情況下,在微服環境中我們都會使用配置中心,這里采用Eureka配置中心,結合Spring Cloud Config實作配置動態重繪,實作這個功能我們需要引入Eureka的依賴,啟動一個注冊中心服務,并修改Spring Cloud Config Server相關配置和Spring Cloud Config Client相關配置,
依賴:
<!--Eureka Server依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
組態檔:
server:
port: 8888
spring:
application:
name: eureka-server
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
啟動類:
@SpringBootApplication
@EnableEurekaServer
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
?修改Spring Cloud Config Server
增加依賴:
<!--Eureka Client依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
修改組態檔(增加eureka 客戶端配置):
spring:
application:
name: config-service
cloud:
config:
server:
git:
uri: https://gitee.com/leonplious/config-server-demo.git
username: xxxx
password: xxxx
default-label: master
search-paths: userservice
server:
port: 28888
eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://localhost:8888/eureka/
instance:
prefer-ip-address: true
修改啟動類(增加@EnableEurekaClient注解):
@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
此時啟動EurekaServer和Spring Cloud Config Server,可以在Eureka上看到Spring Cloud Config Server注冊資訊,

修改Spring Cloud Config Client
增加依賴:
<!--Eureka Client依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
修改組態檔(增加eureka 客戶端配置,修改Config配置資訊):
未使用注冊中心我們指定uri,使用注冊中心之后我們可以直接使用服務名,
server:
port: 18888
spring:
application:
name: userservice
profiles:
active: dev
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8888/eureka
instance:
prefer-ip-address: true
## 加載所有端點
management:
endpoints:
refresh:
enabled: true
web:
exposure:
include: '*'
## 配置中心無法訪問,回傳此資料
user:
username: NaN
password: NaN
---
spring:
profiles: dev
cloud:
config:
discovery:
enabled: true
service-id: config-service # 配置Config Server服務名
# uri: http://localhost:28888
label: master
profile: dev
fail-fast: true
---
spring:
profiles: prod
cloud:
config:
discovery:
enabled: true
service-id: config-service
# uri: http://localhost:28888
label: master
profile: prod
fail-fast: true
修改啟動類(增加@EnableEurekaClient注解):
@SpringBootApplication
@EnableEurekaClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
重新訪問兩個rest端點,可以效果一致,如果需要配置Eureka的高可用集群,在我的《Spring Cloud系列專欄》中有文章可以參考,
?
2.4 Spring Cloud Bus多端重繪
在生產環境中,我們往往會集群部署,此時我使用WebHook來重繪單個端點就顯得很雞肋了,這個時候我們可以使用Spring Cloud Bus來實作多端重繪,它是通過Message Queue來廣播配置更新通知來實作的,
官方介紹地址:
Spring Cloud Bus
我們先安裝RabbitMQ來使用Spring Cloud Bus(官方支持rabbit和kafka)

?修改Spring Cloud Config Client應用中的相關配置和依賴
依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
修改組態檔(參考rabbit配置,其他配置不變):
server:
port: 18888
spring:
application:
name: userservice
profiles:
active: dev
rabbitmq:
host: localhost
port: 5672
password: guest
username: guest
virtual-host: /
此時我們使用IDEA將Spring Cloud Config Client應用使用不同埠啟動兩個服務
選中服務后點擊Edit Configurations…

修改配置,指定埠和服務名,并勾選Allow parallel run

復制一份配置,使用另一埠啟動

此時可以訪問單點Eureka,查看注冊資訊

RabbitMQ上有兩個匿名佇列

此時我們根據不同的埠訪問rest埠
http://localhost:19999/user/user2
http://localhost:18888/user/user2
User2(username=liziba, password=123456)
修改Gitee上的組態檔
user:
username: "Edg"
password: "champion"
如果沒有配置WebHook則使用postman發起一個post請求到http://localhost:18888/actuator/bus-refresh端點,注意這里是bus-refresh,重新訪問兩個rest端點,此時配置資訊已重繪:


轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/354621.html
標籤:java
