支持 gRPC 長連接,深度解讀 Nacos 2.0 架構設計及新模型

頭圖.jpg

做者 | 楊翊(席翁)  Nacos PMC 來源|阿裏巴巴雲原生公衆號python

Nacos 簡介

1.jpeg

Nacos 在阿里巴巴起源於 2008 年五彩石項目,該項目完成了微服務拆分和業務中臺建設,隨着雲計算和開源環境的興起,2018 年咱們深入感覺到開源軟件行業的影響,所以決定將 Nacos 開源,輸出阿里十年關於服務發現和配管管理的沉澱,推進微服務行業發展,加速企業數字化轉型。git

目前 Nacos 支持主流微服務開發語言 & 主流服務框架和配置管理框架,好比支持 Duboo 和 SCA, 還對接了一些雲原生的組件好比 coreDNS 和 sentinel 等。github

客戶端語言方面支持諸如 Java、go python 等主流語言,還有近期剛發佈正式版本的 C# 和 C++,在此感謝全部社區貢獻者的支持。數據庫

2.jpeg

Nacos 開源 2 年多以來,共發佈了 34 個版本,其中有一些比較重要的里程碑版本;Nacos 還很是年輕,有很大的進步空間,歡迎社區及各界大佬一塊兒共同建設。緩存

3.jpeg

Nacos 1.X 架構及問題

接下來咱們看一下 nacos1.x 架構及其分析一下存在的比較重要的問題。首先來看一下架構簡圖。網絡

Nacos 1.X 架構層次

4.jpeg

Nacos 1.X 大體分爲 5 層, 分別是接入、通訊、功能、同步和持久化。數據結構

接入層是用戶最直接交互的層面,主要有 Nacos 客戶端,以及依賴客戶端的 Dubbo 和 SCA 以及用戶操做的控制檯 Console 組成。客戶端和 Console 進行服務和配置操做,統一經過 HTTP 的 OpenAPI 發起通訊請求。架構

通訊層主要基於 HTTP 的短鏈接請求模型進行,部分推送功能經過 UDP 進行通訊。負載均衡

功能目前有服務發現和配置管理,這層也就是實際管理服務和配置的業務層。框架

同步層有數據同步的 AP 模式 Distro 和 CP 模式 Raft,還有有一個最簡易的水平通知 Notify,用處各不相同:

  • Distro:非持久化服務的同步模式。
  • Raft:持久化服務的同步模式、以及使用 Derby 做爲配置的存儲時同步配置操做。
  • Notify:使用 MySQL 做爲配置的存儲時,通知其餘節點更新緩存及發起配置推送。

持久化層 Nacos 使用 MySQL、Derby 和本地文件系統來進行數據的持久化 配置信息,用戶信息,權限信息存儲在 MySQL 或 Derby 數據庫中, 持久化服務信息及服務和實例元數據信息存儲在本地文件系統。

Nacos 1.X 架構下的服務模型

咱們經過一個服務發現的流程,再深刻熟悉一下 Nacos 1.X 架構和基於當前架構的 Nacos 服務發現模型。

5.jpeg

Nacos 客戶端註冊服務會經過 OpenAPI 發送 Http 註冊服務的請求,請求內容會帶上服務信息及實例信息,一般這個步驟是由微服務框架 SCA 和 dubbo 完成。

服務端收到請求後,會先在 Contoller 中進行數據的讀取和校驗,好比 IP 是否合法,服務名是否正確等等。校驗經過後,若是這個服務是第一次註冊,Nacos 會在服務端生成一個 Service 對象,而後把此次註冊的實例信息存入這個 Service 對象中;若是 Nacos 服務端已經有了這個 Service 對象,那麼就會直接把新註冊的實例信息存入對象。這個 Service 對象經過 命名空間+Group+Service 的組合來保證惟一性。

完成實例存入 Service 的同時,會觸發兩個事件,其中一個事件是用於數據同步的,Nacos 服務端會根據這個服務是不是臨時對象的信息,使用 Distro 或者 Raft 協議進行同步,通知其餘的 Nacos 節點該服務發生了變動;另外一個事件則通知在該 Nacos 服務節點上訂閱了該服務的訂閱者,並根據訂閱者信息,經過 UDP 的方式,把最新的服務列表推送到訂閱者客戶端上。這就完成了一次服務註冊流程。

另外,對於那些被定義爲持久化的服務的全部信息,都會經過 raft 協議,保證可以寫入到文件系統中被持久化。

最後,其餘的 Nacos 節點,在經過同步而進行 Service 變動的時候也會觸發通知訂閱者的事件,從而使在其餘 Nacos 服務節點上訂閱該服務的訂閱者也能收到推送。

1.X 架構存在的問題

粗略介紹了下 Nacos1.X 的架構和服務發現模型,接下來分析一下 Nacos1.X 架構所面臨的幾個比較重要的問題。

一句話總結,心跳多,無效查詢多,心跳續約感知變化慢,鏈接消耗大,資源空耗嚴重。

6.jpeg

  • 心跳數量多,致使 TPS 居高不下

經過心跳續約,當服務規模上升時,特別是相似 Dubbo 的接口級服務較多時,心跳及配置元數據的輪詢數量衆多,致使集羣 TPS 很高,系統資源高度空耗。

  • 經過心跳續約感知服務變化,時延長

心跳續約須要達到超時時間纔會移除並通知訂閱者,默認爲 15s,時延較長,時效性差。若改短超時時間,當網絡抖動時,會頻繁觸發變動推送,對客戶端服務端都有更大損耗。

  • UDP 推送不可靠,致使 QPS 居高不下

因爲 UDP 不可靠,所以客戶端測須要每隔一段時間進行對帳查詢,保證客戶端緩存的服務列表的狀態正確,當訂閱客戶端規模上升時,集羣 QPS 很高,但大多數服務列表其實不會頻繁改變,形成無效查詢,從而存在資源空耗。

  • 基於 HTTP 短鏈接模型,TIME_WAIT 狀態鏈接過多

HTTP 短鏈接模型,每次客戶端請求都會建立和銷燬 TCP 連接,TCP 協議銷燬的連接狀態是 WAIT_TIME,徹底釋放還須要必定時間,當 TPS 和 QPS 較高時,服務端和客戶端可能有大量的 WAIT_TIME 狀態連接,從而會致使 connect time out 錯誤或者 Cannot assign requested address 的問題。

  • 配置模塊的 30 秒長輪詢引發的頻繁 GC

配置模塊使用 HTTP 短鏈接阻塞模型來模擬長鏈接通訊,可是因爲並不是真實的長鏈接模型,所以每 30 秒須要進行一次請求和數據的上下文切換,每一次切換都有引發形成一次內存浪費,從而致使服務端頻繁 GC。

Nacos 2.0 架構及新模型

Nacos 2.0 架構層次

Nacos 2.X 在 1.X 的架構基礎上 新增了對長鏈接模型的支持,同時保留對舊客戶端和 openAPI 的核心功能支持。

7.jpeg

通訊層目前經過 gRPC 和 Rsocket 實現了長鏈接 RPC 調用和推送能力。

在服務端測,新增一個連接層,用來將不一樣類型的 Request 請求,未來自不一樣客戶端的不一樣類型請求,轉化爲相同語意的功能數據結構,複用業務處理邏輯。同時,未來的流量控制和負載均衡等功能也會在連接層處理。

其餘架構分層在大致上保持不變。

Nacos 2.0 新服務模型

雖然 Nacos2.0 的在架構層次上並未作太大的變化,可是具體的模型細節卻有不小的改動,依舊使用註冊服務的流程,再深刻了解一下 Nacos2.0 服務模型的變化。

8.jpeg

因爲通訊使用了 RPC 方式,所以某一客戶端的全部請求(不管是註冊仍是訂閱)都經過同一個連接和同一個服務節點進行,不像以前經過 HTTP 鏈接可能每次請求都請求在不一樣的 Nacos 節點上,這就致使了服務發現的數據內容由原來的無狀態化變爲了與鏈接狀態綁定的一種有狀態數據。爲了適應這種變化,須要改變一下數據模型,所以抽象了一個新數據結構,將同一個客戶端經過該連接發佈和訂閱的內容關聯起來,暫命名爲 Client。這個 Client 不是客戶端的意思,而是這個客戶端所相關的數據內容,一個連接與一個 Client 對應。

當客戶端發佈了服務時,該客戶端所發佈的全部服務與訂閱者信息會被更新到與該客戶端連接相對應的 Client 對象中,而後經過事件機制觸發對索引信息的更新。這個索引信息是客戶端連接和服務的索引,方便快速聚合生成須要推送的服務緯度的數據。

索引信息更新完成後,會觸發推送事件,此時會將全部和該服務有關的 Client 對象,經過剛產生的索引信息聚合起來,當數據聚合完成後,再從客戶端連接中篩選出訂閱該服務的訂閱者的客戶端連接,將推送數據經過該連接,推送回去。這樣一次發佈變動的主鏈路就完成了。

回過頭看數據同步,客戶端發佈了服務時實際更新的對象從原來的 Service 變成 Client 對象,因此須要同步的內容也變成了 Client 對象;同時服務端間的通訊方式也會換成 RPC。這裏只有真正被客戶端更新的 Client 對象會觸發同步,若是是經過同步而更新的 Client 對象不會再次觸發同步。

最後看 Metadata,Metadata 是從 1.X 版本中的 Service 對象和 Instance 對象中分離出來的一些屬性:好比服務的元數據 label 標籤,實例的上下線狀態、權重和元數據 label 標籤等。這些元數據能夠被 openAPI 單獨修改,在聚合數據時生效。之因此將元數據拆分出來,區別於基礎數據,緣由是基礎數據好比:ip 端口,服務名等一經發布不該該被修改,並且應當以發佈時的信息爲準;但其餘的原數據,好比上下線狀態和權重,一般是在運行過程當中動態調節的,所以拆分開以後,分爲兩條不一樣的處理工做流應該更加合理。

Nacos 2.0 架構的優缺點

前面簡要介紹了 Nacos 2.0 的架構和新模型的工做方式,接下來咱們分析一下這樣的改動有哪些優缺點。

9.jpeg

優勢

  • 客戶端再也不須要定時發送實例心跳,只須要有一個維持鏈接可用 keepalive 消息便可。重複 TPS 能夠大幅下降。

  • TCP 鏈接斷開能夠被快速感知到,提高反應速度。

  • 長鏈接的流式推送,比 UDP 更加可靠;nio 的機制具備更高的吞吐量,並且因爲可靠推送,能夠加長客戶端用於對帳服務列表的時間,甚至刪除相關的請求。重複的無效 QPS 能夠大幅下降。

  • 長鏈接避免頻繁鏈接開銷,能夠大幅緩解 TIME_ WAIT 問題。

  • 真實的長鏈接,解決配置模塊 GC 問題。

  • 更細粒度的同步內容,減小服務節點間的通訊壓力。

缺點

沒有銀彈的方案,新架構也會引入一些新問題:

  • 內部結構複雜度上升,管理鏈接狀態,鏈接的負載均衡須要管理。

  • 數據又原來的無狀態,變爲與鏈接綁定的有狀態數據,流程鏈路更長。

  • RPC 協議的觀測性不如 HTTP。即便 gRPC 基於 HTTP2.0Stream 實現,仍然不如直接使用 HTTP 協議來的直觀。

Nacos 2.X 規劃

接下來簡單分享下 Nacos 2.X 的後期規劃,主要分爲文檔、質量和 Roadmap。

在文檔和質量方面,Nacos 1.X 都作的不是很好。文檔內容較少,僅有簡單使用文檔;和版本有必定脫節,更新不及時;沒有對技術內容的說明,參與貢獻難度高。代碼質量及測試質量也不是很高,雖然已經使用 checkstyle 進行了 codeStyle 的校驗以及開啓了社區協做 review。可是這還遠遠不夠。Nacos 2.X 將會逐步更新、細化官網使用文檔;經過電子書對技術細節進行解析;經過 Github 展現技術方案,促進討論及貢獻;而且對代碼進行大量重構及 UT 和 IT 的治理工做,在將來將 Benchmark 也會開源出來,方便給開源用戶進行壓測。

10.jpeg

而 RoadMap 方面,Nacos 2.X 會對項目作大幅度的重構,完成初步插件化,並對剛纔 2.0 架構的一些缺點,如負載均衡,可觀測性進行提高。

加入咱們

歡迎在 Nacos github 上提交 issue 與 PR 進行討論和貢獻,或加入 Nacos 社區羣參與社區討論。

除了參與開源,咱們也歡迎更多有能力及有意願的同窗加入阿里雲共建雲原生,詳情請看雲原生應用平臺

本文整理自 Spring Cloud Alibaba Meetup 杭州站演講點擊此處當即參與 1 月 9 日下週六的上海站 Meetup,聽 Nacos 用戶分享 Nacos 在知名互聯網教育公司的落地實踐。

做者簡介

楊翊,花名席翁。Nacos PMC,主要參與的是服務發現模塊,和作一些內核重構和提高的工做。Apache SharadingSphere PMC,主要負責和參與過的模塊有 路由模塊、分佈式事務、 數據同步、以及彈性擴容。

相關文章
相關標籤/搜索