Nacos註冊中心之概要設計
本文已收錄 https://github.com/lkxiaolou/lkxiaolou 歡迎star。
前言
在之前的文章中分析了Nacos配置中心,配置中心的核心是配置的建立、讀取、推送。
註冊中心的核心比配置中心多一個服務探活
模組,他倆的相似度非常高,甚至阿里內部的註冊中心就叫ConfigServer
。
Nacos註冊中心打算分成幾個模組來分析,本文重點在於概要設計
,基於2.0.0版本。
環境搭建
用Nacos的原始碼來搭建原始碼閱讀和除錯環境,可參考《Nacos配置中心模組詳解》 Nacos除錯環境搭建
部分。
其中 JVM引數可以指定只啟動Naming模組,也可以不指定,預設全都啟動。
example模組下將NamingExample複製一份進行測試。
設計概要
服務發現模型
客戶端視角的服務發現模型(注意:服務端視角的模型定義與客戶端視角有區別)包含以下幾點內容:
- Service:服務
- Cluster:叢集
- Instance:例項
程式碼註釋:We introduce a 'service --> cluster --> instance' model, in which service stores a list of clusters, which contains a list of instances
他們的關係如下
Service
- name:服務名
- protectThreshold:保護閾值,限制了例項被探活摘除的最大比例
- appName:服務的應用名,暫無實際用處
- groupName:分組名
- metadata:元資料
Cluster
- serviceName:所屬服務名
- name:叢集名
- healthChecker:服務探活配置,此處僅對服務端主動探活生效,有TCP、HTTP、MySQL、None幾種方式,預設TCP
- defaultPort:預設埠
- defaultCheckPort:預設探活埠
- useIPPort4Check:是否使用port進行探活
- metadata:元資料
Instance
- instanceId:例項id,唯一標誌,Nacos提供了
simple
和snowflake
兩種演算法來生成,預設是simple
ip#port#clusterName#serviceName
- ip:例項ip
- port:例項port
- weight:例項權重
- healthy:例項健康狀態
- clusterName:所屬叢集名
- serviceName:所屬服務名
- metadata:元資料
- enabled:是否接收請求,可用於臨時禁用或摘流等場景
- ephemeral:是否為臨時例項,後文會介紹該引數
- getInstanceHeartBeatInterval:獲取例項心跳上報間隔時間,預設5秒,可配置
- getInstanceHeartBeatTimeOut:獲取心跳超時時間,15秒,配置
- getIpDeleteTimeout:獲取ip被刪除的超時時間,預設30秒,可配置
- getInstanceIdGenerator:獲取id生成器
除了上述的三層模型外,Nacos註冊中心和配置中心有著一樣的namespace設計,與client繫結,可隔離環境,租戶。
介面設計
- registerInstance:註冊例項
- deregisterInstance:登出例項
- getAllInstances:獲取一個服務的所有例項(包括不健康)
- selectInstances:根據條件獲取一個服務的例項
- selectOneHealthyInstance:根據負載均衡策略獲取服務的一個健康的例項
- subscribe:訂閱服務
- unsubscribe:取消訂閱服務
- getServicesOfServer:根據條件分頁獲取所有服務
互動流程
Nacos 2.0 為ephemeral不同的例項提供了兩套流程:
- ephemeral=false,永久例項,與server端的互動採用http請求,server節點間資料同步採用了raft協議,健康檢查採用了server端主動探活的機制
- ephemeral=true,臨時例項,與server端的互動採用grpc請求,server節點間資料同步採用了distro協議,健康檢查採用了TCP連線的KeepAlive模式
臨時例項的互動流程
-
client初始化,與server建立連線
- 只與其中一臺server節點建立長連線
-
client 註冊服務,將serviceName+ip+port+clusterName等資料打包傳送grpc請求
- 同時客戶端快取已註冊過的服務,當client與server連線斷開重連時,client重新將這些資料註冊到server端
-
server端接收到client的註冊請求,將註冊資訊存入client物件(用於儲存client的所有資料)中,並觸發ClientChangedEvent、ClientRegisterServiceEvent、InstanceMetadataEvent
- ClientChangedEvent觸發server節點之間的資料同步(distro協議)
- ClientRegisterServiceEvent觸發更新publisherIndexes(儲存service => clientId的Map<Service, Set
>,即哪些客戶端註冊了這個服務的索引),同時也觸發一個ServiceChangedEvent,該事件負責向監聽該服務的客戶端進行推送 - InstanceMetadataEvent,處理元資料,Nacos在2.0中將元資料與基礎資料拆分開,分為不同的處理流程
-
client訂閱服務
- 根據serviceName、groupName、clusters資訊生成key,建立eventListener,同時向server端傳送訂閱請求,並快取訂閱資訊,用於連線斷開重連後再次向server端傳送資訊
-
server端接收到client的訂閱請求
- 將訂閱資訊打包為subscribers,並存入client物件中,觸發ClientSubscribeServiceEvent事件
- ClientSubscribeServiceEvent事件更新subscriberIndexes(儲存service => clientId的Map<Service, Set
>,即哪些客戶端訂閱了這個服務的索引),同時觸發ServiceSubscribedEvent事件 - ServiceSubscribedEvent事件會延時500ms向該client推送該服務的最新資料
-
反向的操作如登出、取消訂閱與正向操作類似,不再贅述
最後
本文從總體上分析了Nacos 2.0的模型設計、介面設計以及互動流程,讀完後對Nacos的服務發現有一個整體上的認識。
後續篇幅會從細節入手,如dubbo Nacos擴充套件、一致性協議、探活、CMDB擴充套件等逐一進行分析。
搜尋關注微信公眾號"捉蟲大師",後端技術分享,架構設計、效能優化、原始碼閱讀、問題排查、踩坑實踐。