選單

超硬核,Nacos實現原理詳細講解

超硬核,Nacos實現原理詳細講解

Nacos架構

超硬核,Nacos實現原理詳細講解

Provider APP:服務提供者

Consumer APP:服務消費者

Name Server:透過VIP(Virtual IP)或DNS的方式實現Nacos高可用叢集的服務路由

Nacos Server:Nacos服務提供者,裡面包含的Open API是功能訪問入口,Conig Service、Naming Service 是Nacos提供的配置服務、命名服務模組。Consitency Protocol是一致性協議,用來實現Nacos叢集節點的資料同步,這裡使用的是Raft演算法(Etcd、Redis哨兵選舉)

Nacos Console:控制檯

註冊中心的原理

服務例項在啟動時註冊到服務登錄檔,並在關閉時登出

服務消費者查詢服務登錄檔,獲得可用例項

服務註冊中心需要呼叫服務例項的健康檢查API來驗證它是否能夠處理請求

超硬核,Nacos實現原理詳細講解

SpringCloud完成註冊的時機

在Spring-Cloud-Common包中有一個類 ,它是Spring Cloud提供的服務註冊的標準。整合到Spring Cloud中實現服務註冊的元件,都會實現該介面。

該介面有一個實現類是NacoServiceRegistry。

SpringCloud整合Nacos的實現過程:

在包的中包含自動裝配的配置資訊如下:

超硬核,Nacos實現原理詳細講解

其中就是服務註冊相關的配置類:

超硬核,Nacos實現原理詳細講解

在配置類中,可以看到注入了一個例項,該類的關係圖如下所示。

超硬核,Nacos實現原理詳細講解

可以看出, 抽象類實現了該介面,並且最重要的是繼承了。

看到EventListener我們就應該知道,Nacos是透過Spring的事件機制繼承到SpringCloud中去的。

實現了onApplicationEvent抽象方法,並且監聽事件(當Webserver初始化完成之後) , 呼叫方法。

超硬核,Nacos實現原理詳細講解

最終會呼叫方法進行服務註冊。

超硬核,Nacos實現原理詳細講解

NacosServiceRegistry的實現

在方法中,呼叫了Nacos Client SDK中的完成服務的註冊。

超硬核,Nacos實現原理詳細講解

跟蹤NacosNamingService的方法:

超硬核,Nacos實現原理詳細講解

透過建立心跳資訊實現健康檢測, Nacos Server必須要確保註冊的服務例項是健康的,而心跳檢測就是服務健康檢測的手段。

實現服務註冊

心跳機制:

從上述程式碼看,所謂心跳機制就是客戶端透過schedule定時向服務端傳送一個數據包 ,然後啟動-個執行緒不斷檢測服務端的迴應,如果在設定時間內沒有收到服務端的迴應,則認為伺服器出現了故障。Nacos服務端會根據客戶端的心跳包不斷更新服務的狀態。

註冊原理:

Nacos提供了SDK和Open API兩種形式來實現服務註冊。

Open API:

SDK:

這兩種形式本質都一樣,底層都是基於HTTP協議完成請求的。所以註冊服務就是傳送一個HTTP請求:

超硬核,Nacos實現原理詳細講解

對於nacos服務端,對外提供的服務介面請求地址為,實現程式碼咋模組下的InstanceController類中:

超硬核,Nacos實現原理詳細講解

從請求引數彙總獲得serviceName(服務名)和namespaceId(名稱空間Id)

呼叫registerInstance註冊例項

超硬核,Nacos實現原理詳細講解

建立一個控服務(在Nacos控制檯“服務列表”中展示的服務資訊),實際上是初始化一個serviceMap,它是一個ConcurrentHashMap集合

getService,從serviceMap中根據namespaceId和serviceName得到一個服務物件

呼叫addInstance新增服務例項

超硬核,Nacos實現原理詳細講解

根據namespaceId、serviceName從快取中獲取Service例項

如果Service例項為空,則建立並儲存到快取中

超硬核,Nacos實現原理詳細講解

透過方法將服務快取到記憶體

建立心跳機制

實現資料一致性監聽

方法的如下圖所示,它主要透過定時任務不斷檢測當前服務下所有例項最後傳送心跳包的時間。如果超時,則設定healthy為false表示服務不健康,並且傳送服務變更事件。

在這裡請大家思考一一個問題,服務例項的最後心跳包更新時間是誰來觸發的?實際上前面有講到, Nacos客戶端註冊服務的同時也建立了心跳機制。

超硬核,Nacos實現原理詳細講解

putService方法,它的功能是將Service儲存到serviceMap中:

超硬核,Nacos實現原理詳細講解

繼續呼叫addInstance方法把當前註冊的服務例項儲存到Service中:

總結:

Nacos客戶端透過Open API的形式傳送服務註冊請求

Nacos服務端收到請求後,做以下三件事:

構建一個Service物件儲存到ConcurrentHashMap集合中

使用定時任務對當前服務下的所有例項建立心跳檢測機制

基於資料一致性協議服務資料進行同步

服務提供者地址查詢

Open API:

SDK:

InstanceController中的list方法:

超硬核,Nacos實現原理詳細講解

解析請求引數

透過doSrvIPXT返回服務列表資料

超硬核,Nacos實現原理詳細講解

超硬核,Nacos實現原理詳細講解

根據namespaceId、serviceName獲得Service例項

從Service例項中基於srvIPs得到所有服務提供者例項

遍歷組裝JSON字串並返回

Nacos服務地址動態感知原理

可以透過subscribe方法來實現監聽,其中serviceName表示服務名、EventListener表示監聽到的事件:

具體呼叫方式如下:

或者呼叫selectInstance方法,如果將subscribe屬性設定為true,會自動註冊監聽:

Nacos客戶端中有一個HostReactor類,它的功能是實現服務的動態更新,基本原理是:

客戶端發起時間訂閱後,在HostReactor中有一個UpdateTask執行緒,每10s傳送一次Pull請求,獲得服務端最新的地址列表

對於服務端,它和服務提供者的例項之間維持了心跳檢測,一旦服務提供者出現異常,則會發送一個Push訊息給Nacos客戶端,也就是服務端消費者

服務消費者收到請求之後,使用HostReactor中提供的processServiceJSON解析訊息,並更新本地服務地址列表

最近面試BAT,整理一份面試資料《

Java面試BATJ通關手冊

》,覆蓋了Java核心技術、JVM、Java併發、SSM、微服務、資料庫、資料結構等等。

文章有幫助的話,在看,轉發吧。

謝謝支援喲 (*^__^*)