客戶端詳解
在學習瞭如何配置Spring Cloud Config配置中心後,現在我們需要一個客戶端來使用配置中心。
服務化配置中心
在微服務體系中,任何模塊都應該服務化,任何需要服務化的東西都只需要向註冊中心進行註冊,就可以簡單快捷的實現其服務化機制,從而讓微服務中的其他服務更能夠發現並使用,所以無疑配置中心需要接入eureka註冊中心,過程我們就不贅述了,前面幾乎每個模塊都進行了類似的操作,只需要在config-server項目中引入eureka並在配置文件中配置註冊中心地址即可,啓動成功後可以在註冊中心管理頁面中看到我們的config-server服務已經成功註冊。
客戶端
直接配置
我們先來看一下如果沒有接入註冊中心的情況下,客戶端如何獲取到配置中心的值,下面我們啓動一個新的springboot項目config-client作爲配置中心客戶端,在配置文件引入如下依賴:
implementation 'org.springframework.cloud:spring-cloud-starter-config'
implementation 'org.springframework.boot:spring-boot-starter-web'
然後在bootstrap.yml中配置我們的配置中心地址即可:
spring:
application:
name: springcloud-learn
cloud:
config:
profile: dev
label: master
uri: http://localhost:6666/
兩個注意點:
- bootstrap文件時優先於應用jar包內的配置文件加載的,所以配置在此文件中可以保證通過配置中心獲取外部配置信息
- spring.application.name應該是配置中心中的{application}部分的名字,如果配置錯誤會導致啓動失敗
配置完成後我們可以簡單的實現一個RESTful接口獲取配置:
@RestController
public class ConfigController {
@Value("${from}")
private String from;
@RequestMapping("/getFrom")
public String from () {
return this.from;
}
}
啓動客戶端後通過調用http://localhost:7777/getFrom
可以得到當前配置中心的值
客戶端服務化
上面的方法雖然也實現了客戶端功能,但是由於在配置文件中存在類似於硬編碼ip和port的行爲,顯然不符合微服務的要求,解決方法相信大家也很明白了,就是萬能的註冊中心,只要將客戶端也接入註冊中心,就可以輕鬆實現服務化。
在依賴中增加eureka依賴並且在配置文件中添加如下配置:
spring:
application:
name: springcloud-learn
cloud:
config:
discovery:
enabled: true
service-id: config-server
profile: dev
# cloud:
# config:
# profile: dev
# label: master
# uri: http://localhost:6666/
eureka:
client:
service-url:
defaultZone: http://peer1:1111/eureka/,http://peer2:1112/eureka/
快速失敗與重試
正如我一直強調的,在微服務中任何時候都不能相信其他服務,要認爲故障一定會出現,那麼這種情況下就要做好故障處理措施,畢竟配置項一般屬於比較重要的信息,如果配置項丟失可能導致業務流程錯誤或者甚至程序崩潰。
- 快速失敗
只需要在配置文件中加入spring.cloud.config.failFast=true就可以實現快速失敗功能,暫時關閉config-server然後重新啓動config-client,在啓動日誌中我們可以看到:
java.lang.IllegalStateException: Could not locate PropertySource and the fail fast property is set, failing
由於配置中沒有啓動,我們的客戶端也直接快速失敗了
- 重試
由於配置中心異常導致其他項目啓動失敗應該並不是最理想的結果,畢竟可能我們希望有個更友好的處理方式,或者由於網絡波動導致的異常的話完全可以通過重新解決,接下來我們就要引入spring-retry和spring-aop依賴:
implementation 'org.springframework.retry:spring-retry'
implementation 'org.springframework.boot:spring-boot-starter-aop'
不需要任何其他配置,再次重啓項目,會看到進行了六次重試之後才報了錯誤,若對於默認重新次數或時間間隔有要求,可以通過配置參數配置:
spring.cloud.config.retry.multiplier 初始重試間隔時間
spring.cloud.config.retry.initial-interval 下一間隔重試時間
spring.cloud.config.retry.max-interval 最大間隔時間
spring.cloud.config.retry.max-attempts 最大重試次數
動態更新
對於配置文件來說有一個很重要的功能是動態更新,如果每次更改都需要重啓項目的話就麻煩了,現在如果修改了git中from值後會發現通過config-client調用的返回值並沒有改變,也就是說沒有動態刷新,實現這個功能需要我們在config-client中新增spring-boot-starter-actuator模塊,其中的/refresh實現了應用配置信息的重新獲取和刷新,添加了依賴後還有兩個需要更改的地方
- 在bootstrap.yml中加入actuator暴露的接口,默認只有health和info,缺少這個配置會報404:
management:
endpoints:
web:
exposure:
include: refresh,health,info
- 在config-client的ConfigController類上添加@RefreshScope用於標誌需要刷新的範圍
此時我們重啓config-client,重新修改git中的from值,再次調用http://localhost:7777/getFrom
發現配置沒有改變,此時通過POST請求調用http://localhost:7777/actuator/refresh
,config-client控制檯中會輸出重新拉取配置中心的日誌,再次調用getFrom接口發現值已經改變了,說明內容已經被更新了
但是不難發現,雖然實現了更新,但是距離動態還是差了一些,總不能每次有了配置變更都需要我們手動調用refresh接口進行更新,顯然需要一個hook機制幫我們來實現這個需求,顯然spring cloud早就幫我們實現好了,也就是下一篇中要講的Spring Cloud Bus