前沿:參考文章,非常建議食用
配置中心(Config)使用詳解
配置中心(Config)和消息總線(Bus)完美使用版
上面的兩篇文章裡面都是config-server向eureka注冊,其它服務根據config-server在eureka中的名稱擷取微服務執行個體後再擷取對應自身的配置檔案,這樣确實可以完成,但是有一個問題,因為這樣config-server需要依賴eureka,即eureka必須先跑起來(即eureka的配置檔案必須在本地),這樣一來如果eureka也想把配置檔案放在github上,他們就會沖突,另一種方法是如果向我後面這樣(章節四)直接指定ip和端口,雖然可以解決問題,将eureka的配置檔案也放在遠端,可是,這樣一來,eureka無法擷取config-server搭建的叢集,兩種方式如下(第一至三節為第一種,第四節為第二種)
一、說明
子產品說明:
子產品名稱 | 說明 |
---|---|
eureka | 服務的注冊中心 |
config-server | springCloud-config的服務中心 |
stock | 庫存子產品 |
user | 使用者子產品 |
步驟如下:
- 服務向eureka中心,報告自身的資訊,如自身子產品在eureka中的服務名稱,以及IP和port
- config-server 子產品需要取對應存放配置檔案的地方(如github,gitlab等)讀取配置,那麼就需要配置這些地方的賬号密碼,以及倉庫和對應的目錄
- stock子產品以及user子產品都需要config-server在eureka中的服務名稱,并設定需要的配置檔案的名稱
- 需要明白在springBoot中bootstrap.properties比application.properties的檔案優先級要高,會首先加載bootstrap.properties
2、建立demo測試
2.1、建立eureka子產品
直接建立一個eureka子產品即可,和以往的springcloud子產品建立一模一樣,
這裡eureka的配置檔案采用本地的方式(關于把eureka的配置檔案也放在git伺服器上,請看文章第四節),這裡就不再啰嗦了
2.2、建立config-server子產品
2.2.1、依賴
因為是springcloud-config的服務端,是以我們需要config的server依賴
<dependencies>
<!--Eureka用戶端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--springCloud-config服務端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
2.2.2、啟動類
需要開啟@EnableConfigServer
@SpringBootApplication
@EnableConfigServer
@EnableDiscoveryClient
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class,args);
}
}
2.2.2、配置檔案
配置檔案如下
spring.application.name=config-server
server.port=9005
eureka.client.serviceUrl.defaultZone= http://localhost:8005/eureka/
eureka.instance.prefer-ip-address = true
spring.cloud.config.server.git.uri = https://github.com/wandun/config-repo
spring.cloud.config.server.git.search-paths = /userModuleConfig,/stockModuleConfig
spring.cloud.config.server.git.username = github的使用者名
spring.cloud.config.server.git.password = github的密碼
spring.cloud.config.server.git.skip-ssl-validation=true
說明:
- spring.application.name: 這個是指定該子產品在eureka中的服務名稱。
- server.port:服務指定的端口。
- eureka.client.serviceUrl.defaultZone: 這個是設定與Eureka Server互動的位址,用戶端的查詢服務和注冊服務都需要依賴這個位址。
- spring.cloud.config.server.git.uri: 配置的Git倉庫的位址,我這裡是專門建立了一個github的倉庫
- spring.cloud.config.server.git.search-paths: git倉庫位址下的相對位址 多個用逗号","分割。
- spring.cloud.config.server.git.username:git倉庫的賬号。
- spring.cloud.config.server.git.password:git倉庫的密碼。
對應上面的 search-paths = /userModuleConfig,/stockModuleConfig,一個目錄對應一個子產品的配置檔案,每一個子產品又都有dev,uat,pro三種配置環境
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL6dGRNpXWq1ENNpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLzATM1QTMyYTM1ETMwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
每一個配置檔案隻有兩項
- tockconfig-dev (uat/pro).properties
server.port=8088 # (stock 子產品的啟動端口)
current.profile=dev # 根據目前的配置檔案(uat ,dev, pro)
- userconfig-dev (uat/pro).properties
server.port=8089 # (user子產品的啟動端口)
current.profile=dev # 根據目前的配置檔案(uat ,dev, pro)
2.3、建立stock子產品
2.3.1、依賴
後面因為需要通過浏覽器通路,是以需要web依賴,而且因為stock是springcloud-config的用戶端,是以我們需要config的client依賴,并且我們需要向eureka注冊,是以我們需要eureka的用戶端
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Eureka用戶端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 配置config用戶端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
2.3.2、啟動類
@SpringBootApplication
@EnableDiscoveryClient
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class,args);
}
}
2.3.2、配置檔案
這個子產品的配置檔案名稱一定一定要是bootstrap開頭,不能是application,因為stock子產品的配置檔案不是讀取本地的application.properties,而是需要去擷取遠端的,是以我們使用bootstrap的 優先級會更高,在加載application之前包配置從遠端讀取到手後就可以了!
spring.cloud.config.name=stockconfig
spring.cloud.config.profile=dev
spring.cloud.config.label=master
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=config-server
eureka.client.serviceUrl.defaultZone=http://localhost:8005/eureka/
eureka.instance.prefer-ip-address = true
說明:
- spring.cloud.config.name: 擷取配置檔案的名稱的字首,請詳細檢視前面倉庫說明截圖
- spring.cloud.config.profile: 擷取配置的政策,dev,uat,pro
spring.cloud.config.label:擷取配置檔案的分支,預設是master。如果是- 是本地擷取的話,則無用。
-spring.cloud.config.discovery.enabled: 開啟配置資訊發現。
- spring.cloud.config.discovery.serviceId: 指定配置中心(config-server)在eureka中的service-id
- eureka.client.serviceUrl.defaultZone: 這個是設定與Eureka Server互動的位址,用戶端的查詢服務和注冊服務都需要依賴這個位址。
- eureka.instance.prefer-ip-address: 在eureka中顯示具體的ip
這裡stock子產品為什麼可以找到config-server服務,是通過前面的配置
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=config-server
因為config-server再eureka中進行了注冊
2.3.3、編寫測試接口
我這裡在對應的子產品寫了一個接口,擷取目前配置檔案中的current.profile的值,因為我們之前在每一個環境中的配置檔案對應的值是不同的,是以隻要我們切換環境,那麼配置會發生變化,current.profile值也就會發生變化
@RestController
public class StockController {
private static final String currentProjectName = "stock";
@Value("${current.profile}")
private String currentProfile;
/**
* 測試配置是否及時生效
* @return
*/
@GetMapping("/getCurrentProfile")
public String getCurrentProfile(){
return currentProjectName+":"+currentProfile==null?"null":currentProfile;
}
}
2.4、建立user子產品
這個子產品與stock子產品建立一緻,隻是配置檔案不同,因為兩個子產品的配置檔案的位址也不同,如下
# 擷取配置檔案的名稱
spring.cloud.config.name=userconfig
spring.cloud.config.profile=dev
spring.cloud.config.label=master
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=config-server
eureka.client.serviceUrl.defaultZone=http://localhost:8005/eureka/
eureka.instance.prefer-ip-address = true
2.5、測試
先請求一次我們呢之前配置的那個接口,更改配置後(需要重新開機),再去請求一次,會發生變化
3、自動重新整理配置
過程如下:
- 1、送出配置觸發post請求給server端的bus/refresh接口
- 2、server端接收到請求并發送給Spring Cloud Bus總線
- 3、Spring Cloud bus接到消息并通知給其它連接配接到總線的用戶端
- 4、其它用戶端接收到通知,請求Server端擷取最新配置
- 5、全部用戶端均擷取到最新的配置
以上通信使用的是amqp(其實作又rabbitmq),或者你可以使用kafka
3.1、改變config-server
3.1.1、pom.xml的修改
增加actuator依賴,和bus-amqp依賴
<!--
通過 bus通知配置的修改(實作是通過消息中間件 amqp),
再通過 actuator 的開放的端口,自動重新整理配置(這樣隻要一改變配置,我們的用戶端就會收到資訊)
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
3.1.2、application.properties的修改
需要開啟actuator 的bus-refresh端點,開啟bus的發現,通知功能,并配置通知消息的中間件的位址賬号以及密碼,即增加如下配置
# 開啟actuator 的bus-refresh端點
management.endpoints.web.exposure.include= bus-refresh
#spring.cloud.bus.enabled = true
#spring.cloud.bus.trace.enabled = true
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
3.2、改變用戶端
這裡我就隻修改stock這一個用戶端,作為列子,user用戶端就不再改了
3.2.1、pom.xml的修改
增加actuator依賴,和bus-amqp依賴
<!-- 監聽config-server在消息中間件中發出的配置,來跟新配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
3.2.2、bootstrap.properties的修改
需要開啟actuator 的bus-refresh端點,開啟bus的發現,通知功能,并配置通知消息的中間件的位址賬号以及密碼,即增加如下配置
# 開啟actuator 的bus-refresh端點
management.endpoints.web.exposure.include= bus-refresh
#spring.cloud.bus.enabled = true
#spring.cloud.bus.trace.enabled = true
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
3.2.3、增加注解
在使用到配置檔案中的值的位置,增加注解 @RefreshScope,這個很重要,如果沒有這個注解,配置還是不會重新整理,如下
但是如果修改的是spring中官方配置(如改變了jdbc的連接配接使用者沒和密碼等等),則不需要請求rereshe接口,但是如果是自定義的,那麼就需要請求rereshs接口
3.3、rabbitmq安裝
這個就省略了,大家自行百度,用win或者linux都可以
3.4、測試
- 1、依次啟動eurek,config-server,stock,請求我們自己寫的接口,擷取目前的current.profile的值
-
http://localhost:8088/getCurrentProfile
-
- 2、然後修改github倉庫中對應配置檔案的current.profile的值
- 3、再使用postman發送post請求,請求config-server的服務9005,不用擔心actuator/bus-refresh這個接口沒有寫,actuator子產品已經做了,(actuator子產品中會有多個端口,用來檢測目前項目的健康情況,大家也可以去百度自行了解以下springcloud-actuator子產品)
http://localhost:9005/actuator/bus-refresh
- 4、請求完成,我們再請求我們自己的接口,就會發現,配置就是你修改完後的數值了
4、完善
前面本地檔案中還是有eureka和config-server,現在我們也可以把eureka的配置檔案上傳到git伺服器上本地檔案隻有config-server,那麼其它服務就不能再通過eureka中的服務名稱來尋找config-server,而且config-server也不能向eureka注冊了,我們要做的就在配置檔案bootstarp.properties中指定config-server的位址!
是以我們這裡在我們的github的倉庫中再增加一個eureka的目錄和3個環境的配置檔案
最後将eureka項目的application.properties檔案替換成bootstrap.properties即可,内容如下
# 擷取配置檔案的名稱
spring.cloud.config.name=eureka
spring.cloud.config.profile=dev
spring.cloud.config.label=master
# 需要知道 config-server服務的位址
spring.cloud.config.uri=http://localhost:9005
# 開啟actuator 的bus-refresh端點(讀取配置的用戶端可以不開啟)
#management.endpoints.web.exposure.include=bus-refresh
#spring.cloud.bus.enabled = true
#spring.cloud.bus.trace.enabled = true
# 接收 config-server的bus發出的配置修改的資訊,以及時擷取最新配置
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
stock和user子產品的修改,即将前面配置中的
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=config-server
改為
# 需要知道 config-server服務的位址,不能通過eureka中的服務名稱去找,
# 因為eureka本身還需要先知道config-server的位址,會自相沖突
spring.cloud.config.uri=http://localhost:9005
不再通過serviceId尋找,而是通過指定的ip+port找config-server
啟動順序
config-server -----> eureka -----> stock/user
5、後言
關于服務知道config-server的位址有兩種方式
- 第一種,通過config-server在eureka中注冊後其它服務根據serviceId來尋找,(但是需要将config-server注冊到eureka中)
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=config-server
- 第二種,指定位址ip+port
# 需要知道 config-server服務的位址,不能通過eureka中的服務名稱去找,
# 因為eureka本身還需要先知道config-server的位址,會自相沖突
spring.cloud.config.uri=http://localhost:9005
其實第一中和第二種可以混合使用,但是如果想要eureka的配置檔案不在本地,那麼在eureka的bootstrap.properties配置檔案中就必須使用第二種方式,其它服務可以通過第一種,(但是前提是需要在config-server中指定eureka的位址),啟動順序不變,隻是一開始config-server會抛出異常,是因為找不到eureka,等我們把eureka跑起來後,就可以了,大約幾秒後eureka中就會有config-server這個服務,其它服務就可以根據serviceId來找config-server了,為什麼其它服務不直接也使用第二種方式呢?其實可以使用,但是如果我們想給confih-server搭建叢集的話,就隻能使用第一種方式了,但是即使這樣,還是存在一個問題,那就是eureka擷取不到config-server的叢集執行個體!
以上是我個人的一點總結,斯卡帕,如果文章有問題,還望各位看官海涵,可以在下方評論指出,謝謝!