Nacos 服務註冊與發現原理分析

逅弈逐碼 發表於 2022-12-08

Nacos 另一個非常重要的特性就是服務註冊與發現,說到服務的註冊與發現相信大家應該都不陌生,在微服務盛行的今天,服務是非常重要的,而在 Nacos 中服務更被稱為他的一等公民。

Nacos 支援幾乎所有主流型別的 “服務” 的發現、配置和管理。

瞭解過 Dubbo 的同學,應該對 Dubbo 的架構非常熟悉,最經典的一張架構圖如下所示:

Nacos 服務註冊與發現原理分析

圖中的6個步驟的含義解釋如下:

0、服務容器負責啟動,載入,執行服務提供者。

1、服務提供者在啟動時,向註冊中心註冊自己提供的服務。

2、服務消費者在啟動時,向註冊中心訂閱自己所需的服務。

3、註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連線推送變更資料給消費者。

4、服務消費者,從提供者地址列表中,基於軟負載均衡演算法,選一臺提供者進行呼叫,如果呼叫失敗,再選另一臺呼叫。

5、服務消費者和提供者,在記憶體中累計呼叫次數和呼叫時間,定時每分鐘傳送一次統計資料到監控中心。

其中圖中最上方的 Registry 就是註冊中心,負責服務的註冊與發現。Dubbo 有自己的 Registry 實現,而 Nacos 則是另一種 Registry 的實現。

現在我們來了解下 Nacos 的服務註冊與發現,首先在本地將 Nacos 服務端啟動起來,具體怎麼操作這裡不再贅述,不清楚的同學可以參考我的其他文章。

模擬服務註冊

我們模擬將同一個服務的兩個例項註冊到 Nacos 中,程式碼如下圖所示:

Nacos 服務註冊與發現原理分析

透過 NamingService 介面的 registerInstance 方法就可以將服務進行註冊了,該方法有很多過載的方法,這裡我們選擇一個簡單的來呼叫就好了。

註冊完成後,透過呼叫 getAllInstances 方法,立即獲取所有可用的例項,然後讓主執行緒等待,列印如下:

Nacos 服務註冊與發現原理分析

從列印結果中可以發現 naming 客戶端成功獲取到了兩個例項。

模擬服務發現

服務註冊之後,服務的消費者就可以向註冊中心訂閱自己所需要的服務了,註冊中心會將所有服務的例項“推送”給消費者,這裡我在推送上打了引號,原因是實際上獲取服務是客戶端主動輪詢的,跟客戶端獲取配置中心的配置項的原理一樣。這裡不進行具體的描述,有興趣的可以跟一下程式碼就知道了。

現在我建立一個服務消費者,然後向註冊中心訂閱一個服務,當接收到註冊中心返回的服務列表之後,執行5次 select 服務例項的操作,相當於進行一個模擬的服務請求,具體的程式碼如下圖所示:

Nacos 服務註冊與發現原理分析

其中的 printInstances 方法主要是列印出所有服務的例項,為了節省篇幅就不寫出來了,將 ServiceConsumer 類啟動之後,列印出如下的日誌:

Nacos 服務註冊與發現原理分析

消費者每次獲取一個健康的例項進行呼叫,接下來我就來分析下整個服務註冊與發現的過程和大致的設計原理和思路。

服務如何註冊

服務註冊最重要的就是將服務註冊到哪裡,在註冊中心服務端,肯定有一個用來管理服務的容器,他儲存著所有服務的例項。

我們暫時不需要知道該容器具體的實現細節,只需要知道有這樣一個概念。

Nacos 服務註冊與發現原理分析
Nacos 服務註冊與發現原理分析
Nacos 服務註冊與發現原理分析
Nacos 服務註冊與發現原理分析

服務如何發現

服務註冊到註冊中心後,服務的消費者就可以進行服務發現的流程了,消費者可以直接向註冊中心傳送獲取某個服務例項的請求,這種情況下注冊中心將返回所有可用的服務例項給消費者,但是一般不推薦這種情況。另一種方法就是服務的消費者向註冊中心訂閱某個服務,並提交一個監聽器,當註冊中心中服務發生變更時,監聽器會收到通知,這時消費者更新本地的服務例項列表,以保證所有的服務均是可用的。

Nacos 服務註冊與發現原理分析
Nacos 服務註冊與發現原理分析

負載均衡

負載均衡有很多種實現方式,包括輪詢法,隨機方法法,對請求ip做hash後取模等等,從負載的維度考慮又分為:服務端負載均衡和客戶端負載均衡。

Nacos 的客戶端在獲取到服務的完整例項列表後,會在客戶端進行負載均衡演算法來獲取一個可用的例項,模式使用的是隨機獲取的方式。

Nacos 服務註冊與發現原理分析

Nacos 服務註冊與訂閱的完整流程

Nacos 客戶端進行服務註冊有兩個部分組成,一個是將服務資訊註冊到服務端,另一個是像服務端傳送心跳包,這兩個操作都是透過 NamingProxy 和服務端進行資料互動的。

Nacos 客戶端進行服務訂閱時也有兩部分組成,一個是不斷從服務端查詢可用服務例項的定時任務,另一個是不斷從已變服務佇列中取出服務並通知 EventListener 持有者的定時任務。

Nacos 服務註冊與發現原理分析

官方提供的demo具有一定的迷惑性,不過這能迫使你去了解事物的本質。

你如果直接官方的demo,你會發現如下有趣的情況:

1、第一次註冊了兩個例項,獲取例項時返回的是2個

2、然後解除註冊其中的一個例項,再次獲取例項時返回的還是2個

3、訂閱服務的監聽器將會收到兩次 onEvent 回撥,第一次是2個例項,第二次是1個例項

按照正常的情況,註冊了兩個例項,然後解除註冊了一個只會,再次獲取例項應該返回1個例項才對,但是返回了2個。

深入瞭解下原始碼就能知道原因:

客戶端將獲取到的服務例項儲存在一個 map 中,而該 map 中的內容是由排程任務定時去更新的,存在一定的延時。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69908605/viewspace-2671497/,如需轉載,請註明出處,否則將追究法律責任。