上兩個章節講述了Nacos在單機模式下的服務注冊,發現等原始碼剖析程序,實戰當中
其實單機是遠遠不夠的,那么Nacos是如何在集群模式下是如何保證節點狀態同步,以及服
務變動,新增資料同步的程序的!
重要幾個點:
1、Nacos心跳在集群架構下的設計原理剖析
2、Nacos集群節點+服務狀態同步原始碼剖析
3、Nacos集群服務新增資料同步原始碼剖析
4、Nacos集群節點增加后資料同步原始碼剖析
1、集群環境下如何進行本地除錯
單機版本我在前面的章節已經講述如何部署,那么集群條件下按照以下步驟
需要先配置mysql存盤,在mysql里新建一個庫,我這邊命名nacos_config
選中nacos原始碼的distribution/conf下的sql腳本,在剛創建的資料庫執行下即可!
然后修改console模塊下的application.properties的mysql配置
因為我這里模擬三臺,所以我需要在我的磁盤上建立三個檔案夾
D:\nacos-cluster\nacos-8847\conf
D:\nacos-cluster\nacos-8848\conf
D:\nacos-cluster\nacos-8849\conf,里面放cluster.conf,
cluster.conf里配置本機ip加三個埠模擬三臺集群
192.168.1.9:8847 192.168.1.9:8848 192.168.1.9:8849Idea做三個主啟動類分別加上引數
-Dserver.port=8847 -Dnacos.home=D:\nacos-cluster\nacos-8847
準備好后我們啟動三臺完畢
隨便訪問一臺試試
到這我們原始碼模擬集群搭建程序就完成!
2、Nacos心跳在集群架構下的設計原理剖析
前面我們已經講述過單機下的心跳機制,Nacos Server端會開啟一個定時心跳檢查任務,來保證某個服務的健康狀態的檢查;你想下如果在集群下,會采用每個Nacos都開啟定時對每個服務做心跳檢查嗎?如果都開啟的話,那么心跳之間要相互的同步資料,保證大家的資訊都是基本一致,一旦集群數量越多,那么這個成本是不是越高,兩兩同步,甚至更多,所以Nacos在集群環境下并非這樣設計,而是只在一臺對當前的服務上定時心跳檢查,有任何變動,通知其他節點即可!
在ClientBeatCheckTask里,如果你問我怎么找到的,看看我前面的章節就可以了,
在這個run里面之前我有講過下面的檢查邏輯,而上面的邏輯我是跳過的,
進入responsible方法,大概的瀏覽下,前面的判斷先過去,重點一看就有一個distroHash這個方法;
進入distroHash里面,邏輯是服務名取hashCode的值對Integer的最大值取余
我們可以debug看下這個值是多少
server有三臺,所以這個target的值是2,在第三臺上
每一臺機器都會走這段邏輯,這段我舉個例子:
假設有三臺:192.168.1.9:8847 192.168.1.9:8848 192.168.1.9:8849
server[0]:192.168.1.9:8847
server[1]:192.168.1.9:8848
server[2]:192.168.1.9:8849
有個服務注冊上來了,每個服務端會維護一個servers,里面存放上面三個IP+Port,此時第一臺8847開始執行心跳檢查,進入responsiable方法,判斷當前的ip在不在這個List里,如果在,回傳當前的index索引,這個index范圍在[0-2],再判斷最后出現的索引的地方,如果當前IP已經不在servers中,直接回傳true,取非就是false,那么當前節點就做這個服務的健康檢查(這點不理解為什么),如果當前IP在這個servers中,開始對服務進行取模到一臺上,回傳
target >= index && target <= lastIndex其實在我看來index和lastIndex值是一樣的,因為ip和埠正常來說不會重復出現在list,里,所以這塊我不理解為什么要多判斷一次,target值一定也是[0-2]之間,所以如果index=1,target=2,這個判斷就是false,取反就是true,當前節點不做該服務的健康檢查,因為index=1說明當前節點是8848這臺,而target表示落點在server[2]上,說明到server[2]這臺上,該服務做健康檢查,其他節點,該服務不做健康檢查直接return掉了,每次相同的服務只定位到那臺機器上做健康檢查任務,
所以說到這里,原理就已經大概清楚了,
那么問題就來了,如果三臺有一臺掛了呢?那取模不就有問題了?
接著往下看,有個ServerListManager.init方法,我也是在之前看到了有個類GlobalExcutor里面全是scheduled定時任務才知道在這里,當然我也猜到了集群中的節點同步,通常肯定是放在定時任務里的;于是才找到這個init方法,
這里有個registerServerStatusReporter,存在一個引數ServerStatusReporter,是個執行緒,
搞個for回圈后,給所有服務節點發送個心跳
然后呼叫的是url的一個介面,每臺機器都會提供一個狀態的介面,/operator/servers/status,實際上每臺機器都會呼叫其他兩臺機器的這個介面告訴他我還活著,那么如果當前機器死了,另外兩臺機器就收不到該機器的心跳了,默認就會把自己的serverlist這三臺機器更新成2臺,所以剛剛的hash運算即便服務掛了也不會出現問題,
那么心跳在集群模式下的設計原理和心跳狀態同步機制就講到這,
3、Nacos集群節點+服務狀態同步原始碼剖析
那么光有心跳不行啊,如果某個服務不健康了,或者要被踢下線了,這幾臺服務之間是如何感知的呢?
我是通過剛剛的send方法,發現了另一個實作ServiceStatusSynchronizer,見明知意是服務狀態同步器,然后看看哪里呼叫send方法,最后發現是在ServiceManager.init里進行的呼叫,
在ServiceManager類里有個私有類ServiceReporter也是個執行緒,debug看下里面是發送的什么資訊,實際上發送到其他節點,告訴他到底該服務咋了,是不健康了,還是要剔除,
那主線就到這結束,如果感興趣可以自行深入往下研究,
4、Nacos集群服務新增資料同步原始碼剖析
如果我們有一臺新的節點注冊上去,那么集群之間是怎么進行新增資料同步的呢?
這個類在前面章節講過
DistroConsistencyServiceImpl.put方法有個distroProtocol.sync
里面搞了個for回圈,allMembersWithoutSelf 如果是單機,這就是空的,for回圈就結束了,但是集群的話,拿到除開自己的其他節點
這段代碼講實話我看了很久,繞的一批,不知道寫這個為啥要這樣嗎,我大概說下,里面做了distroKeyWithTarget是除開自己的機器,把當前的distorKey和目標機器封裝起來,然后添加到一個任務去執行;
這里又很類似一個異步套路,既然往里去put,就一定有地方去get
下面有一個方法processTasks執行佇列的任務,首先把任務移出來,
移出來的任務判斷當前這個任務是不是為慷訓者應該被執行,如果不是,就直接移出來回傳當前的任務物件AbstractDelayTask,繼續往下看呼叫getProcessor(taskKey)
然后看下try的processor.process(task),關鍵在于
distroTaskEngineHolder.getExecuteWorkersManager().addTask(distroKey, syncChangeTask);這個方法
往里看走到了worker.process(task)
最終放到一個阻塞queue佇列里
既然有put就有take,通常會在當前的類中TaskExecuteWorker,執行task.run方法
我這里直接debug下去的,進入到DistroSyncChangeTask.run方法
然后進入syncData里面,這里也有個syncData方法
最終進入到真正的同步api里,把資料同步到其他節點上,
所以說這段代碼太繞了,不知道搞這么多異步佇列做什么,當然我不是原始碼開發的人,只是站在一個角度看不明白而已哈哈,
那么如果同步資料失敗了就重試,
5、Nacos集群節點增加后資料同步原始碼剖析
那么如果這個時候我新加了節點進來,這個資料又是如何同步到新的節點上多呢?
這個我也找了半天,剛剛上一節描述了節點之間的資料同步的原始碼后發現到的
還是和同步syncData一樣的類DistroProtocol構造方法有個startDistroTask()
開啟一個加載資料的任務
這個Task又是一個執行緒,看run方法
進入load方法,里面會去加載遠端機器的資料,存到一個map里
再進去看看,走到getDatumSnapshot(each.getAddress())
又呼叫了這個NamingProxy,老眼熟了,里面就是http介面方法,
看下引數
最侄訓是走到了http的介面上呼叫其他服務的方法,通過HttpClient拉取資料到自己的服務上,
這里要注意下,新加進來的機器不是每個機器都去找,它只會找一個機器去同步,
這個會不會出現有段時間節點之間資料不一致的問題啊,當然會有,ap架構下的Nacos集群就會有這樣的問題,但是ap架構是最終一致性的,這個關系其實不大,找不到再去其他節點上找就是了,如果你想保證資料的強一致性,那就用到cp架構,后面我再更新,
所以最終你把整體的架構把握了就可以,真正遇到問題的時候,再去追蹤細節,
喜歡的話一鍵三連吧!!哈哈
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/299490.html
標籤:其他
上一篇:資料清洗的概述

















那么心跳在集群模式下的設計原理和心跳狀態同步機制就講到這,


















看下引數

