用Nacos做微服務架構里的服務注冊與發現中心


轉自:https://www.jianshu.com/p/61608ff86344

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

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

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

 

 

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

0、服務容器負責啟動,加載,運行服務提供者。
1、服務提供者在啟動時,向注冊中心注冊自己提供的服務。
2、服務消費者在啟動時,向注冊中心訂閱自己所需的服務。
3、注冊中心返回服務提供者地址列表給消費者,如果有變更,注冊中心將基於長連接推送變更數據給消費者。
4、服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一台提供者進行調用,如果調用失敗,再選另一台調用。
5、服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鍾發送一次統計數據到監控中心。

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

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

模擬服務注冊

我們模擬將同一個服務的兩個實例注冊到 Nacos 中,代碼如下圖所示:

 

 

通過 NamingService 接口的 registerInstance 方法就可以將服務進行注冊了,該方法有很多重載的方法,這里我們選擇一個簡單的來調用就好了。

注冊完成后,通過調用 getAllInstances 方法,立即獲取所有可用的實例,然后讓主線程等待,打印如下:

 

 

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

模擬服務發現

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

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

service-consumer.jpg

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

 
service-consumer-effect.jpg

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

服務如何注冊

服務注冊最重要的就是將服務注冊到哪里,在注冊中心服務端,肯定有一個用來管理服務的容器,他保存着所有服務的實例。

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

 

 

nacos-registry-princple-1.jpg
 

 

nacos-registry-princple-2.jpg
 

 

nacos-registry-princple-3.jpg
 

 

nacos-registry-princple-4.jpg

服務如何發現

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

 

 

nacos-registry-princple-5.jpg
 

 

nacos-registry-princple-6.jpg

負載均衡

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

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

 

 

nacos-registry-princple-7.jpg

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

Nacos 客戶端進行服務注冊有兩個部分組成,一個是將服務信息注冊到服務端,另一個是像服務端發送心跳包,這兩個操作都是通過 NamingProxy 和服務端進行數據交互的。

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

 

 

nacos-service-register-found.png

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

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

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

2、然后解除注冊其中的一個實例,再次獲取實例時返回的還是2個

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

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

深入了解下源碼就能知道原因:

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

 


免責聲明!

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



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