前言
對於微服務而言配置本地化是個很大的雞肋,不可能每次需要改個配置都要重新把服務重新啟動一遍,因此最終的解決方案都是將配置外部化,託管在一個平臺上達到不用重啟服務即可一次修改多處生效的目的。
但是對於單體應用的Spring Boot專案而言,動態重新整理顯然是有點多餘,反正就一個服務,改下重啟不就行了?
然而在某些特殊的場景下還是必須用到動態重新整理的,如下:
新增資料來源:對接某個第三方平臺的時候,你不可能每次新增一個數據源都要重啟下服務
固化的對接:大量的固定對接方式,只是其中的某個固定的程式碼段不同,比如提供檢視中的欄位不同,介面服務中欄位不同等情況。
當然以上列舉的兩種場景每個公司都有不同的解決方案,這裡不做深究。
微服務下有哪幾種主流的方案?
微服務下的動態配置中心有三種主流的方式,如下圖:
上圖中的三種配置中心方案可以說是現在企業中使用率最高的,分別是:
Nacos
:阿里巴巴的最近開源的專案,這個傢伙很牛逼,一個幹掉了Eureka(停更)和Config+Bus,既能作為配置中心也能作為註冊中心,並且有自己的獨立的 管理平臺,可以說是現在最主流的一種。
Config+Bus
:早期在用的微服務配置中心,可以依託GitHub管理微服務的配置檔案,這種現在也是有不少企業在用,但是需要自己獨立部署一個微服務,和Nacos相比遜色了不少。
Apollo
:攜程開源專案Apollo,這個也是不少企業在用,陳某瞭解的不多,有興趣的可以深入研究下。
針對Spring Boot 適用的幾種方案?
其實上述三種都可以在Spring Boot專案中適配,但是作為單體應用有些重了,下面作者簡單的介紹兩種可用的方案。
Spring Boot+Nacos(不推薦)
不得不說阿里巴巴確實挺有野心,阿里要做的其實是一個微服務生態,Nacos不僅僅可以作為Spring Cloud的配置和註冊中心,也適配了Dubbo、K8s,官方文件中對於如何適配都做了詳細的介紹,作者 這裡就不再詳細介紹了,如下圖:
當然Nacos對Spring、Spring Boot 專案同樣適用。
如何使用呢?這裡作者只提供下思路,不做過多的深究,這篇在作者下個專欄
Spring Cloud 進階
會詳細介紹:
下載對應版本的Nacos,啟動專案,訪問http://localhost:8848進入Nacos的管理介面;
Spring Boot 專案引入Nacos的配置依賴nacos-config-spring-boot-starter,配置Nacos管理中心的地址。
@NacosPropertySource、@NacosValue兩個註解結合完成。
@NacosPropertySource:指定配置中心的dataId,和是否自動重新整理
@NacosValue替代@Value註解完成屬性的自動裝配
如果公司專案做了後臺管理,則可以直接呼叫Nacos開放的API修改對應配置的值(替代了Nacos管理介面的手動操作),API的地址:nacos。io/zh-cn/docs/…
此種方案雖說可以實現配置的動態重新整理,但是還要整合Nacos,啟動一個Nacos的服務,完全是有點大材小用了,實際專案中不推薦使用。
Spring Boot+Config+actuator(推薦)
此種方案實際使用的是Config配置中心,但是不像Nacos那般重,完全適用於單體應用的SpringBoot專案,只需要做小部分的更改即可達到效果。
方案一(不推薦)
新增Config的依賴,如下:
<!—— springCloud的依賴——>
配置檔案中暴露Spring Boot的端點,如下:
management。endpoints。web。exposure。include=*
配置檔案中新增三個屬性配置:
config。version=22config。app。name=dynamic-projectconfig。platform=mysql
結合@RefreshScope註解動態重新整理,寫個Controller,如下:
@RestController//@RefreshScope該註解必須標註,否則無法完成動態更新@RefreshScopepublic class DynamicConfigController { @Value(“${config。version}”) private String version; @Value(“${config。app。name}”) private String appName; @Value(“${config。platform}”) private String platform; @GetMapping(“/show/version”) public String test(){ return “version=”+version+“-appName=”+appName+“-platform=”+platform; }
啟動專案測試,瀏覽器訪問http://localhost:8080/show/version,返回資訊如下圖:
修改target目錄下的配置檔案,如下:
config。version=33config。app。name=dynamic-projectconfig。platform=ORACLE
POST請求http://localhost:8080/actuator/refresh介面,手動重新整理下配置(必須,否則不能自動重新整理)
瀏覽器再次輸入http://localhost:8080/show/version,結果如下圖:
可以看到,配置已經自動修改了,結束。
方案二(推薦)
看到了方案一覺得如何?是不是有點雞肋了
第一個問題:為什麼還要呼叫一次手動重新整理呢?
第二個問題:只能手動的在配置檔案中改嗎?如果想在後臺管理系統改怎麼辦?
想要解決上述兩個問題還是要看下Config的原始碼,程式碼關鍵部分在org。springframework。cloud。context。refresh。ContextRefresher#refresh()方法中,如下圖:
因此只需要在修改屬性之後呼叫下ContextRefresher#refresh()(非同步,避免一直阻塞等待)方法即可。
為了方便測試,我們自己手動寫一個refresh介面,如下:
@GetMapping(“/show/refresh”) public String refresh(){ //修改配置檔案中屬性 HashMap
上述程式碼中作者只是手動設定了配置檔案中的值,實際專案中可以透過持久化的方式從資料庫中讀取配置重新整理。
下面我們測試看看,啟動專案,訪問http://localhost:8080/show/version,發現是之前配置在application。properties中的值,如下圖:
呼叫refresh介面:http://localhost:8080/show/refresh重新設定屬性值;
再次呼叫http://localhost:8080/show/version檢視下配置是否修改了,如下圖:
從上圖可以發現,配置果然修改了,達到了動態重新整理的效果。
總結
本文從微服務的配置中心介紹到Spring Boot 搭建簡易的配置中心,詳細介紹了幾種可行性的方案,作者強力推薦最後一種方案,簡化版的Config,完全適用於單體應用。
作者:碼猿技術專欄
連結:https://juejin。cn/post/6977169384787673096