Nacos通過RefreshScope實(shí)現(xiàn)配置自動更新的方式分享
實(shí)現(xiàn)方式
有兩種方式,使用 @ConfigurationProperties
注解調(diào)用get請求或者 @RefreshScope + @Value
這兩種來實(shí)現(xiàn)配置的刷新。
配置屬性
現(xiàn)象
初始值是false,修改Nacos中的配置文件為true。很快配置項(xiàng)就變了。
idea日志
可以看到是觸發(fā)了配置的更新并打印了配置變化項(xiàng)。
DEBUG
通過Debug知道大體流程如下:
配置更新的大體流程如上。NacosClient中使用了一個線程池的無線循環(huán)來監(jiān)測配置的變更,即長輪詢的方式去Nacos Server中去獲取配置變更。
自動刷新
從上面我們可以得到配置已經(jīng)更新到了Environment中,但是持有配置項(xiàng)的類由于已經(jīng)初始化是不會變更已經(jīng)設(shè)置進(jìn)去的屬性。容器工廠通過銷毀bean,重建bean的方式來重新初始化配置對象,達(dá)到整個配置更新的操作。
配置刷新(@ConfigurationProperties)
refreshEnvironment(刷新環(huán)境變量)
刷新環(huán)境變量同時通過對比找出變更的配置項(xiàng),再觸發(fā)環(huán)境改變Event事件。
ConfigurationPropertiesRebinder(配置重新綁定)
配置重新綁定類同步也實(shí)現(xiàn) ApplicationListener
接口,監(jiān)聽了 EnvironmentChangeEvent
的改變。是通過beanFactory來銷毀bean和初始化bean。
疑問?
由于Spring框架的限制,當(dāng)刷新配置項(xiàng)時,所有的配置項(xiàng)都會刷新,走bean的銷毀和創(chuàng)建過程。往往我們只需要更新其中變化的配置項(xiàng)即可。
已經(jīng)得到了變更的配置項(xiàng)了,結(jié)果還是刷新了所有的配置項(xiàng)。如果不需要進(jìn)行刷新,也可以添加自定義的配置項(xiàng),把對應(yīng)的配置加進(jìn)來即可。
默認(rèn)是hikari數(shù)據(jù)庫連接池的datasource對象。防止刷新時造成數(shù)據(jù)庫連接池重新銷毀創(chuàng)建,造成連接的浪費(fèi)。
其實(shí)我們可以通過keys想辦法定位對應(yīng)的配置項(xiàng),在Environment中附加每一個屬性對應(yīng)的來源。這樣可以直接通過變量操作來源進(jìn)行對應(yīng)的配置刷新。如果想粒度更小的話,在初始化過程中反射設(shè)置屬性時,可以只設(shè)置變更的屬性,最小的代價(jià)變更配置類的變量值。
單例,通過反射的方式設(shè)置配置變更項(xiàng)。可以通過get方式來獲取變量后的值。
變量刷新(@RefreshScope + @Value)
非配置類上配置了 @RefreshScope
注解后,在abstractApplicationContext中實(shí)例化bean時沒有走單例或者原型的初始化方式。是通過Scope的方式自定義bean的獲取方式。
Scope內(nèi)部會維護(hù)一個數(shù)組緩存刷新對象。每次獲取時從緩存內(nèi)部獲取對象,如果不存在則重新創(chuàng)建,就會重新走一遍對象的實(shí)例化,因此Value對象就會重新被賦值。
緩存清除
依據(jù)配置,同理可以知道也是通過event機(jī)制獲取到配置更新,進(jìn)而去清除緩存。我們debug一下調(diào)用??匆幌?。
最后其實(shí)就是調(diào)用了cache的clear方法,清除了所有緩存。再次獲取bean時,緩存中不存在,就會重新進(jìn)行創(chuàng)建。
疑問?
這里也是清除所有緩存,所有 @RefreshScope
類都會重新創(chuàng)建。雖然對應(yīng)的配置也會更新,但是也會觸發(fā)postConstruct,destory等方法,導(dǎo)致出現(xiàn)一些無法預(yù)料的問題。應(yīng)用自動刷新同時也要考慮上述的情況,盡量進(jìn)行規(guī)避。
總結(jié)
個人建議走配置更新的方式。通過每次使用get方法來獲取到最新的變量即可。配置類沒有被重新創(chuàng)建,開銷更小,框架也是自動已經(jīng)集成好了。SpringBoot中可能變量設(shè)置方式可能非常多,導(dǎo)致不能準(zhǔn)確定位到變量對應(yīng)的配置類,所以每次都是刷新所有的配置類和注解類,開銷也很大。
以上就是詳解Nacos如何通過RefreshScope實(shí)現(xiàn)配置自動更新的詳細(xì)內(nèi)容,更多關(guān)于Nacos RefreshScope自動更新的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解Jenkins 實(shí)現(xiàn)Gitlab事件自動觸發(fā)Jenkins構(gòu)建及釘釘消息推送
這篇文章主要介紹了Jenkins 實(shí)現(xiàn)Gitlab事件自動觸發(fā)Jenkins構(gòu)建及釘釘消息推送,應(yīng)該會對大家學(xué)習(xí)Jenkins有所啟發(fā)2021-04-04Java中HashMap和Hashtable的區(qū)別淺析
這篇文章主要介紹了Java中HashMap和Hashtable的區(qū)別淺析,本文總結(jié)了6條它們之間的不同之處,需要的朋友可以參考下2015-03-03文件路徑正確,報(bào)java.io.FileNotFoundException異常的原因及解決辦法
這篇文章主要介紹了文件路徑正確,報(bào)java.io.FileNotFoundException異常的原因及解決辦法的相關(guān)資料,需要的朋友可以參考下2016-04-04spring cloud gateway 全局過濾器的實(shí)現(xiàn)
全局過濾器作用于所有的路由,不需要單獨(dú)配置,我們可以用它來實(shí)現(xiàn)很多統(tǒng)一化處理的業(yè)務(wù)需求,這篇文章主要介紹了spring cloud gateway 全局過濾器的實(shí)現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-03-03springboot如何獲取application.yml里值的方法
這篇文章主要介紹了springboot如何獲取application.yml里的值,文章圍繞主題相關(guān)自資料展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-04-04