Nacos入門


1. Nacos入門

1.1. 前言

我的初衷是想搞一套適合自定義快速開發的框架,把一些必要的技術整合進來,第一想法是嘗試下SpringCloud Alibaba,畢竟是阿里開發,適應國人需求,下載源碼本打算研究下,看了nacos,就想到之前項目用的Eureka,而我也深知Eureka真的只是單純的注冊中心,需要配置屬性還要依賴git做配置中心,所以改用nacos或許也是不錯的主意,於是開始研究nacos

1.2. 部署配置

我這入門和普通的運行demo入門不一樣,直接看源碼說話,先把SpringCloud Alibaba的git代碼下下來

由於nacos是個單獨部署的服務,所以先去Nacos官網安裝好nacos,賬號密碼都是nacos,修改配置文件nacos地址

UTOOLS1587006812859.png

1.3. 控制台配置

  1. 可以看到上述配置文件,明顯一個dataId對應了一個配置文件,group做為分組參數,我們可以再nacos界面進行配置
    UTOOLS1587007099274.png

UTOOLS1587007136853.png

點擊發布,確認后就可以更新到應用,那么現在來研究它的原理

1.4. 調試分析

1.4.1. 獲取配置

隨意發布更新一個配置看到打印參數

UTOOLS1587007279721.png

那么進ClientWorker類,可以看到一個單獨的線程池負責了數據的接收

UTOOLS1587008234346.png

其中核心的更新配置方法為checkUpdateDataIds,而該方法內部的核心方法為checkUpdateConfigStr,其核心內容如下

UTOOLS1587008427496.png

明顯可以看到一個遠程post調用的方法,此方法用來獲取nacos的最新配置,到這里可能要問了,明明是nacos修改配置推送給客戶端,為什么是客戶端調用服務端?這里nacos用了個巧妙的方法,設置較長的超時時間,看截圖可以看出,超時時間為45秒,實際上nacos在30秒的時候若沒有修改數據,就會返回空數據表示沒有更新,若30秒以內有更新數據,則可以在這個45秒的請求中直接返回,看到這個設計我還真有點佩服作者腦洞的,這樣做相當於把心跳和數據傳輸結合起來了,不需要再額外搞個心跳連接,一旦nacos掛了,客戶端就會報錯,客戶端在請求則nacos也知道客戶端存活。我能想到的劣勢,或許就是這樣的長連接不能搞太多吧,但一般服務連接也夠了

接下來進入方法parseUpdateDataIdResponse,該方法用來確認修改了哪份配置,真正修改系統配置的還要回去繼續看

UTOOLS1587113169850.png

可以看到changedGroupKeys為改變的文件,nacos在拿到改變文件名稱后,會通過getServerConfig方法主動去獲取改變數據

UTOOLS1587113440349.png

之后通過LocalConfigInfoProcessor.saveSnapshot在本地存一個快照,更新本地緩存cacheMap

1.4.2. 刷新配置

  1. 遍歷緩存配置文件名
    UTOOLS1587176202353.png

  2. 檢測數據變化

UTOOLS1587176288333.png

  1. 刷新屬性值

UTOOLS1587178947860.png

  1. 刷新容器,加載新的配置文件

UTOOLS1587180002722.png

  1. 加載對應環境配置文件
    UTOOLS1587188713982.png

  2. 資源定位器
    UTOOLS1587180364218.png

  3. 讀取位置,這里讀取的是故障轉移文件,也就是可以放自己的配置文件在nacos故障的時候可以使用

UTOOLS1587181016398.png

  1. 一般沒有故障轉移文件,則遠程調用獲取正確配置

UTOOLS1587188316038.png

  1. 構建PropertySource

UTOOLS1587188516105.png

1.5. 總結

整個流程下來可以總結為幾步

  1. 保持遠程連接,拉取改變的文件名
  2. 根據拉取的文件名,dataId等參數獲取真正的配置數據
  3. 更新緩存中配置,這里我發現好多地方都會經過configFilterChainManager.doFilter(null, cr),我通過反射添加了過濾器,結果一次文件更新會調用好多遍doFilter,目前沒搞清它的意義是什么
  4. 發布配置更新事件RefreshEvent,會重新加載propertySource,過程中會遠程調用Nacos再次去調用最新配置

1.6. 問題

沒想明白這冗余的設計,隨着源碼的深入,真的反轉反轉再反轉,劇情跌宕起伏

  1. 我以為在阻塞請求中會直接返回改變的配置參數,結果返回的是nacos中配置的文件名,好吧,這也可以理解,文件名用來定位具體的propertySource也行,但為什么不和改變參數一起返回;
  2. 那好,根據第一次返回的參數再去遠程調用獲取配置,我以為可能只返回修改的參數,返回的卻是整個文件參數,好吧,這樣容錯更好也能理解,就是一次可能傳遞的數據量會比較多,似乎和apollo的設計不同
  3. 我以為拿到數據應該會去更新環境變量,刷新實例了,但是也沒有,對着緩存操作了一通,然后直接刷新Spring容器,通過它早就定義好的資源定位器,重新遠程讀取配置內容,刷新到propertySource
  4. 好吧,中間的一系列操作,我姑且認為為其它依賴做准備,但多次出現的configFilterChainManager.doFilter(null, cr)又看不懂了,看名字應該是鏈式過濾器,但哪有過濾器再一次更新中調用3次以上的,而且在沒刷新容器之前,也起不到過濾作用吧;
  5. 並且這個過濾器定義了add方法,但我沒找到入口可以添加,只能通過反射強制讀出屬性進行過濾器的添加
  6. 我也看到了listener.receiveConfigInfo(contentTmp);這么個方法,這個更像是對用戶提供的配置內容讀取方法,若想要拿到配置變動后新的配置信息,可別用filter去了,實現的例子如下

UTOOLS1587198454703.png


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM