1. 程式人生 > 其它 >Nacos註冊中心之概要設計

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提供了simplesnowflake兩種演算法來生成,預設是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擴充套件等逐一進行分析。


搜尋關注微信公眾號"捉蟲大師",後端技術分享,架構設計、效能優化、原始碼閱讀、問題排查、踩坑實踐。