Nacos註冊中心學習筆記

前言

英文全稱Dynamic Naming and Configuration Service,Na爲naming/nameServer即註冊中心,co爲configuration即註冊中心,service是指該註冊/配置中心都是以服務爲核心。服務在nacos是一等公民。

在學習Nacos之前先來思考一個問題:註冊中心應設計爲AP還是CP系統?

參考《阿里巴巴爲什麼不用 ZooKeeper 做服務發現?》http://jm.taobao.org/2018/06/13/%E5%81%9A%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0%EF%BC%9F/

這篇文章的描述,阿里在很早就開始思考這個問題,對註冊中心來說,AP和CP究竟哪種系統更加適合,在文中已經有詳細的論證和闡述,簡單來說,CP系統因爲強一致性而只能放棄高可用性,但可用性對於註冊中心來講其實更爲重要,註冊中心不能因爲自身的任何原因破壞服務之間本身的可連通性,這是註冊中心設計應該遵循的鐵律!一旦註冊中心出現不可用,那服務的上線下線均受到影響,註冊中心客戶端雖然可以通過緩存等手段解決一部分可用性問題,但並無法完全避免可用性的缺失對服務間通信帶來的影響。AP系統缺失了強一致性,文中提到會導致一定的流量不均衡,但隨着最終一致性,流量不均衡的問題最終可以解決,但筆者認爲,除了不均衡問題之外,服務下線信息如果沒辦法做到強一致性,還會導致增加服務失敗的概率,這種服務失敗的情況是否能夠被業務場景所接受,也是需要考慮的因素,該如何解決和避免,是否應該在註冊中心客戶端層來對失敗服務的ip做一定封鎖,需要進一步思考。但總體來講,比較認同AP系統更加適合作爲註冊中心這一結論。

下面就幾個方面來介紹一下nacos註冊中心的關鍵要點:

一、nacos如何進行服務註冊、探活

服務註冊方法:以Java nacos client v1.0.1 爲例子,服務註冊的策略的是每5秒向nacos server發送一次心跳,心跳帶上了服務名,服務ip,服務端口等信息。同時 nacos server也會向client 主動發起健康檢查,支持tcp/http檢查。如果15秒內無心跳且健康檢查失敗則認爲實例不健康,如果30秒內健康檢查失敗則剔除實例。

Zookeeper 和 Eureka 都實現了一種 TTL 的機制,就是如果客戶端在一定時間內沒有向註冊中心發送心跳,則會將這個客戶端摘除。Eureka 做的更好的一點在於它允許在註冊服務的時候,自定義檢查自身狀態的健康檢查方法。這在服務實例能夠保持心跳上報的場景下,是一種比較好的體驗,在 Dubbo 和 SpringCloud 這兩大體系內,也被培養成用戶心智上的默認行爲。Nacos 也支持這種 TTL 機制,不過這與 ConfigServer 在阿里巴巴內部的機制又有一些區別。Nacos 目前支持臨時實例使用心跳上報方式維持活性,發送心跳的週期默認是 5 秒,Nacos 服務端會在 15 秒沒收到心跳後將實例設置爲不健康,在 30 秒沒收到心跳時將這個臨時實例摘除。

不過正如前文所說,有一些服務無法上報心跳,但是可以提供一個檢測接口,由外部去探測。這樣的服務也是廣泛存在的,而且以我們的經驗,這些服務對服務發現和負載均衡的需求同樣強烈。服務端健康檢查最常見的方式是 TCP 端口探測和 HTTP 接口返回碼探測,這兩種探測方式因爲其協議的通用性可以支持絕大多數的健康檢查場景。在其他一些特殊的場景中,可能還需要執行特殊的接口才能判斷服務是否可用。例如部署了數據庫的主備,數據庫的主備可能會在某些情況下切換,需要通過服務名對外提供訪問,保證當前訪問的庫是主庫。此時的健康檢查接口,可能就是一個檢查數據庫是否是主庫的 MYSQL 命令了。

客戶端健康檢查和服務端健康檢查有一些不同的關注點。客戶端健康檢查主要關注客戶端上報心跳的方式、服務端摘除不健康客戶端的機制。而服務端健康檢查,則關注探測客戶端的方式、靈敏度及設置客戶端健康狀態的機制。從實現複雜性來說,服務端探測肯定是要更加複雜的,因爲需要服務端根據註冊服務配置的健康檢查方式,去執行相應的接口,判斷相應的返回結果,並做好重試機制和線程池的管理。這與客戶端探測,只需要等待心跳,然後刷新 TTL 是不一樣的。同時服務端健康檢查無法摘除不健康實例,這意味着只要註冊過的服務實例,如果不調用接口主動註銷,這些服務實例都需要去維持健康檢查的探測任務,而客戶端則可以隨時摘除不健康實例,減輕服務端的壓力。

 

二、nacos的數據模型

註冊中心的核心數據是服務的名字和它對應的網絡地址,當服務註冊了多個實例時,我們需要對不健康的實例進行過濾或者針對實例的一些特徵進行流量的分配,那麼就需要在實例上存儲一些例如健康狀態、權重等屬性。隨着服務規模的擴大,漸漸的又需要在整個服務級別設定一些權限規則、以及對所有實例都生效的一些開關,於是在服務級別又會設立一些屬性。再往後,我們又發現單個服務的實例又會有劃分爲多個子集的需求,例如一個服務是多機房部署的,那麼可能需要對每個機房的實例做不同的配置,這樣又需要在服務和實例之間再設定一個數據級別。

Nacos註冊中心的設計原理詳解

服務分級模型

Nacos註冊中心的設計原理詳解

服務邏輯隔離模型

Nacos 提供了四層的數據邏輯隔離模型,用戶賬號對應的可能是一個企業或者獨立的個體,這個數據一般情況下不會透傳到服務註冊中心。一個用戶賬號可以新建多個命名空間,每個命名空間對應一個客戶端實例,這個命名空間對應的註冊中心物理集羣是可以根據規則進行路由的,這樣可以讓註冊中心內部的升級和遷移對用戶是無感知的,同時可以根據用戶的級別,爲用戶提供不同服務級別的物理集羣。再往下是服務分組和服務名組成的二維服務標識,可以滿足接口級別的服務隔離。

 

三、nacos如何保證一致性

數據一致性是分佈式系統永恆的話題,Paxos 協議的艱深更讓數據一致性成爲程序員大牛們吹水的常見話題。不過從協議層面上看,一致性的選型已經很長時間沒有新的成員加入了。目前來看基本可以歸爲兩家:一種是基於 Leader 的非對等部署的單點寫一致性,一種是對等部署的多寫一致性。當我們選用服務註冊中心的時候,並沒有一種協議能夠覆蓋所有場景,例如當註冊的服務節點不會定時發送心跳到註冊中心時,強一致協議看起來是唯一的選擇,因爲無法通過心跳來進行數據的補償註冊,第一次註冊就必須保證數據不會丟失。而當客戶端會定時發送心跳來彙報健康狀態時,第一次的註冊的成功率並不是非常關鍵(當然也很關鍵,只是相對來說我們容忍數據的少量寫失敗),因爲後續還可以通過心跳再把數據補償上來,此時 Paxos 協議的單點瓶頸就會不太划算了,這也是 Eureka 爲什麼不採用 Paxos 協議而採用自定義的 Renew 機制的原因。

這兩種數據一致性協議有各自的使用場景,對服務註冊的需求不同,就會導致使用不同的協議。Nacos 因爲要支持多種服務類型的註冊,並能夠具有機房容災、集羣擴展等必不可少的能力,在 1.0.0 正式支持 AP 和 CP 兩種一致性協議並存。1.0.0 重構了數據的讀寫和同步邏輯,將與業務相關的 CRUD 與底層的一致性同步邏輯進行了分層隔離。然後將業務的讀寫(主要是寫,因爲讀會直接使用業務層的緩存)抽象爲 Nacos 定義的數據類型,調用一致性服務進行數據同步。在決定使用 CP 還是 AP 一致性時,使用一個代理,通過可控制的規則進行轉發。

目前的一致性協議實現,一個是基於簡化的 Raft 的 CP 一致性,一個是基於自研協議 Distro 的 AP 一致性。Raft 協議不必多言,基於 Leader 進行寫入,其 CP 也並不是嚴格的,只是能保證一半所見一致,以及數據的丟失概率較小。Distro 協議則是參考了內部 ConfigServer 和開源 Eureka,在不借助第三方存儲的情況下,實現基本大同小異。Distro 重點是做了一些邏輯的優化和性能的調優。

Nacos註冊中心的設計原理詳解

四、nacos的負載均衡策略

負載均衡嚴格的來說,並不算是傳統註冊中心的功能。一般來說服務發現的完整流程應該是先從註冊中心獲取到服務的實例列表,然後再根據自身的需求,來選擇其中的部分實例或者按照一定的流量分配機制來訪問不同的服務提供者,因此註冊中心本身一般不限定服務消費者的訪問策略。

nacos支持服務端的負載均衡,服務端的負載均衡,給服務提供者更強的流量控制權,但是無法滿足不同的消費者希望使用不同負載均衡策略的需求。而不同負載均衡策略的場景,確實是存在的。而客戶端的負載均衡則提供了這種靈活性,並對用戶擴展提供更加友好的支持。但是客戶端負載均衡策略如果配置不當,可能會導致服務提供者出現熱點,或者壓根就拿不到任何服務提供者。

Nacos註冊中心的設計原理詳解

同時,nacos支持基於標籤的負載均衡,新提供了基於第三方 CMDB 的標籤負載均衡器,具體可以參考CMDB 功能介紹文章。使用基於標籤的負載均衡器,目前可以實現同標籤優先訪問的流量調度策略,實際的應用場景中,可以用來實現服務的就近訪問,當您的服務部署在多個地域時,這非常有用。使用這個標籤負載均衡器,可以支持非常多的場景。

理想的負載均衡實現應該是什麼樣的呢?不同的人會有不同的答案。Nacos 試圖做的是將服務端負載均衡與客戶端負載均衡通過某種機制結合起來,提供用戶擴展性,並給予用戶充分的自主選擇權和輕便的使用方式。負載均衡是一個很大的話題,當我們在關注註冊中心提供的負載均衡策略時,需要注意該註冊中心是否有我需要的負載均衡方式,使用方式是否複雜。如果沒有,那麼是否允許我方便的擴展來實現我需求的負載均衡策略。

Nacos 既支持客戶端的健康檢查,也支持服務端的健康檢查,同一個服務可以切換健康檢查模式。我們認爲這種健康檢查方式的多樣性非常重要,這樣可以支持各種類型的服務,讓這些服務都可以使用到 Nacos 的負載均衡能力。Nacos 下一步要做的是實現健康檢查方式的用戶擴展機制,不管是服務端探測還是客戶端探測。這樣可以支持用戶傳入一條業務語義的請求,然後由 Nacos 去執行,做到健康檢查的定製。

五、nacos的多活策略

集羣擴展性和集羣容量以及讀寫性能關係緊密。當使用一個比較小的集羣規模就可以支撐遠高於現有數量的服務註冊及訪問時,集羣的擴展能力暫時就不會那麼重要。

集羣擴展性的另一個方面是多地域部署和容災的支持。當講究集羣的高可用和穩定性以及網絡上的跨地域延遲要求能夠在每個地域都部署集羣的時候,我們現有的方案有多機房容災、異地多活、多數據中心等。

Nacos註冊中心的設計原理詳解

Nacos 的多機房部署和容災

Nacos 支持兩種模式的部署,一種是和 Eureka 一樣的 AP 協議的部署,這種模式只支持臨時實例,並支持機房容災。另一種是支持持久化實例的 CP 模式,這種情況下不支持雙機房容災。

在談到異地多活時,很巧的是,很多業務組件的異地多活正是依靠服務註冊中心和配置中心來實現的,這其中包含流量的調度和集羣的訪問規則的修改等。機房容災是異地多活的一部分,但是要讓業務能夠在訪問服務註冊中心時,動態調整訪問的集羣節點,這需要第三方的組件來做路由。異地多活往往是一個包含所有產品線的總體方案,很難說單個產品是否支持異地多活。

多數據中心其實也算是異地多活的一部分。Nacos 基於阿里巴巴內部的使用經驗,提供的解決方案是纔有 Nacos-Sync 組件來做數據中心之間的數據同步,這意味着每個數據中心的 Nacos 集羣都會有多個數據中心的全量數據。Nacos-Sync 是 Nacos 生態組件裏的重要一環,不僅會承擔 Nacos 集羣與 Nacos 集羣之間的數據同步,也會承擔 Nacos 集羣與 Eureka、Zookeeper、Kubernetes 及 Consul 之間的數據同步。

Nacos註冊中心的設計原理詳解

Nacos 的多數據中心方案

參考文章:

1、服務註冊中心架構演進 https://www.jianshu.com/p/5014bb302c7d

2、什麼是Nacos?Nacos註冊配置中心介紹 https://www.jianshu.com/p/39ade28c150d

3、阿里巴巴爲什麼不用 ZooKeeper 做服務發現? http://jm.taobao.org/2018/06/13/%E5%81%9A%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0%EF%BC%9F/

4、Nacos 註冊中心的設計原理詳解  https://www.infoq.cn/article/B*6vyMIKao9vAKIsJYpE?utm_source=tuicool&utm_medium=referral

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章