如上圖,從架構上就可以看出與disconf之類的有很大不同,主要差別在于:
配置的存儲方式不同
disconf是把配置資訊儲存在mysql、zookeeper中,而spring cloud config是将配置儲存在git/svn上 (即:配置當成源代碼一樣管理)
配置的管理方式不同
spring cloud config沒有類似disconf的統一管理界面,既然把配置都當成git之類的源碼來看待了,git的管理界面,就是配置的管理界面
配置變化的通知機制不同
disconf中配置變化後,依賴zk的事件watcher來通知應用,而spring cloud config則是依賴git每次push後,觸發webhook回調,最終觸發spring cloud bus(消息總線),然後由消息總線通知相關的應用。
另外,spring cloud config server本身也是一個微服務,跟其它的微服務一樣,也可以注冊到eureka server上,讓其它使用方從注冊中心來發現,單純從解決的問題/場景來看,disconf與spring cloud config server是高度重合的,很難說哪個好,那個差,隻是設計哲學不同。
但有一點,從配置變化的通知機制上看,如果有100個應用節點,都依賴于統一配置,如果修改了配置,隻想讓某幾個節點"灰階"更新配置,spring cloud config server更容易做到,這一點相對disconf更靈活(後面會詳細講解)。
使用步驟:
一、在git/svn上建立一個配置項目(用于儲存配置檔案)
application.yml裡的内容如下:
其它幾個檔案application_xxx.yml,裡面的xxx,代表不同的profile.
二、建立config-server微服務
2.1 添加依賴項
關鍵是第2個依賴項
2.2 application.yml
注意上面的cloud.config.server這段,裡面配置了git配置項目的位置。另外:config-server服務本身也需要HA,是以本示例中起了2個執行個體,分别對應server1、server2 這二個profile,用不同的端口,在本機跑2個執行個體,以模拟高可用。
application-server1.yml
application-server2.yml
2.3 main入口類
關鍵是@EnableConfigServer 這個注解。
2.4 跑起來看看
可以看到2個config-server已經注冊到eureka上了,然後單獨浏覽一下: http://localhost:8004/application-dev.yml
已經把git上的application-dev.yml的内容輸出了。
三、使用config-server
3.1 在之前的service-provider中添加依賴項
3.2 建立一個簡單的配置類
然後找一個示例服務,使用這個配置:
3.3 添加bootstrap.yml 配置檔案
注意spring.cloud這一節的内容,裡面指定了profile為dev,讀取的git配置檔案分支為master,同時允許從eureka上自動發現config-server這個執行個體。另外 spring.applicatin.name 即為配置檔案的名稱(即:application_xxx.yml)
3.4 跑起來看看
說明已經從config-server取到了配置。
四、配置更新
4.1 Controller上添加@RefreshScope
這個注解,根據源碼上的說法:Beans annotated this way can be refreshed at runtime and any components that are using them will get a new instance on the next method call, fully initialized and injected with all dependencies. 使用該注解後,可以在運作時直接重新整理Bean,并在下次方法調用時,得到一個全新的執行個體。
4.2 手動重新整理/refresh
可以嘗試把git配置項目裡的application-dev.yml修改下内容,再浏覽剛才的http://localhost:8001/user/1 發現内容并沒有變化。
http://localhost:8001/refresh 手動向這個位址,發一個post請求(可以用postman或 curl -d '' http://localhost:8001/refresh),可以看到
說明demo.title這個配置項被重新整理了,再浏覽http://localhost:8001/user/1 可以看到有變化了
但是這樣顯然不是個辦法,比如有10個service-provider組成的叢集,如果要1台台手動重新整理,太low了(除了做配置灰階更新,可以先重新整理1台這種場景外)
4.3 內建spring cloud bus來批量重新整理
spring cloud bus目前僅支援rabbitmq 及 kafka,我們以kafka為例,先在service-provider的application.yml裡,加入下面的配置
然後依賴項裡,加入:
配置好這些後,本機啟動kafka,然後再重新開機service-provider,就會多出一個/bus/refresh的端點,即:http://xxx:port/bus/refresh ,隻要向叢集中的任何一台機器的/bus/refresh發起post請求,就會同步重新整理其它所有節點。原理大緻就是,這台機器會發一條消息到kafka中,然後其它機器都是挂在消息總線上的,也會監聽到該消息,然後重新整理各自的配置。
最後一個問題:就算有/bus/refresh,也需要有人或系統觸發。這個很好解決,github或gitlab上一般都有webhook功能,可以配置在代碼push時,觸發一些位址的回調。
這樣,隻要配置的代碼送出了,就會觸發自動重新整理。
注:低版本的spring-cloud-dependencies有一個嚴重bug,調用/bus/refresh後,會導緻所有服務節點,從eureka server的執行個體清單中永久下線,無法自動恢複,除非再次通路某個服務的/health端點,建議使用Dalston.SR2 或以上版本。