架構解析:Dubbo3 應用級服務發現如何應對雙11百萬叢集範例

2022-12-01 15:00:26

繼業務全面上雲後,今年雙11,阿里微服務技術棧全面遷移到以 Dubbo3 為代表的雲上開源標準中介軟體體系。在業務上,基於 Dubbo3 首次實現了關鍵業務不停推、不降級的全面使用者體驗提升,從技術上,大幅提高研發與運維效率的同時地址推播等資源利用率在一些關鍵場景提升超 40%,基於三位一體的 Dubbo3 開源中介軟體體系打造了阿里在雲上的單元化最佳實踐和統一標準,同時將規模化實踐經驗與技術創新貢獻開源社群,成為微服務開源技術與標準發展的核心源泉與推動力。

面對百萬規模的叢集範例,實現關鍵鏈路不停推、資源利用率大幅提升的關鍵即是 Dubbo3 中新引入的應用級服務發現。接下來我們著重講解 Dubbo3 應用級服務發現的詳細方案,同時通過餓了麼案例來說明其升級遷移過程。

餓了麼自去年 11月份啟動 Dubbo3 相關的升級工作,在此之前餓了麼的服務架構是用的 是 HSF2,從 HSF2 到 Dubbo3 的總體升級過程經歷了半年,目前已基本完成,有近 2000 個應用、10w 個節點已經跑在 Dubbo3 之上。
通過這次分享,主要想給大家同步餓了麼的 Dubbo3 升級經驗,為什麼升級 Dubbo3、升級的具體流程以及中間遇到的問題、尤其是餓了麼重點關注的應用級服務發現模型,如何完成了地址發現模型的升級以及最終效果。當然在此之前,我們先對 Dubbo3 及應用級服務發現做一個全面的介紹。

關於 Dubbo3 的簡介,期望通過這部分帶大家瞭解 Dubbo3 到底是什麼,與 2.7 架構的主要區別是什麼,提供了哪些特性、可以解決哪些實際的問題等;其中也包括大家都關心相容性、升級成本以及與 HSF2 的關係等。

我們定義 Dubbo3 是下一代的雲原生服務架構,但 3.0 架構到底都包含哪些內容那?

我們先一起看看 3.0 的一些核心設計原則:首先,從架構層面 Dubbo 是面向雲原生設計的,支援超大規模的微服務叢集實踐 - 百萬範例級別,期望通過智慧化流量排程系統提升系統穩定性與吞吐量;在策略層面,Dubbo3 的核心將是毫無保留開源的,它將成為國內公有云事實標準的服務架構,得到各大公有云廠商的支援,並通過靈活的 SPI 擴充套件機制支援不同部署場景的客製化化需求;而在業務價值上,Dubbo3 將顯著降低單機資源消耗,提升全鏈路資源利用率與服務治理效率。

這就是 3.0 設計過程中遵循的核心原則或目標,讓我們從一個更高的層面認識了 Dubbo3。

具體到選型 Dubbo3 框架,大家一定關心 Dubbo3 提供了哪些新功能,如果是 Dubbo 老使用者的話,還關心 Dubbo3 的相容性,總結起來就是 Dubbo3 的遷移成本以及其能帶來的核心價值。

左邊這部分是關於  Dubbo3 相容性及來源的詳細描述。首先 Dubbo3 是從其自身 2.0 架構演進而來,因此它繼承了 2.0 幾乎所有的特性,且保持了對 Dubbo2 的完全相容,因此,老使用者幾乎可以零成本遷移到 Dubbo3。Dubbo3 是在企業實踐經驗的基礎上演進而來,我們知道 Dubbo 最初是由阿里開源並貢獻給 Apache 社群,而這一次,阿里也已將 Dubbo3 定位為其下一代服務架構,因此,Dubbo3 融合了 HSF2 的幾乎所有服務治理特性,並且已經開始在阿里巴巴全面取代 HSF2 框架,這一點我們在後面企業實踐部分還會講到。

右邊是 Dubbo3 提供的核心特性列表,主要包括四部分。

  • 全新服務發現模型。應用粒度服務發現,面向雲原生設計,適配基礎設施與異構系統;效能與叢集伸縮性大幅提升
  • 下一代 RPC 協定 Triple。基於 HTTP/2 的 Triple 協定,相容 gRPC;閘道器穿透性強、多語言友好、支援 Reactive Stream
  • 統一流量治理模型。面向雲原生流量治理,SDK、Mesh、VM、Container 等統一治理規則;支援更豐富的流量治理場景
  • Service Mesh。Sidecar Mesh 與 Proxyless Mesh,更多架構選擇,降低遷移、落地成本

這張圖更直觀的反映了 Dubbo3 產生的背景以及與一些重要產品之間的關係。Dubbo3 誕生的基礎是 Dubbo2、HSF2 兩款產品,同時以雲原生架構作為指導思想進行了大量重構,並規劃一系列的功能特性;這些共同組成了 Dubbo3,也就是我們在 github 倉庫及開源官網上看到的 Dubbo3;而在開源 Dubbo3 產品之上那,我們有基於 Dubbo3 的企業實踐使用者、生態產品以及公有云廠商的雲產品。比如大家比較關心的 Dubbo3 典型使用者阿里巴巴,阿里巴巴內部在此之前一直執行在自研 HSF2 框架,當然鑑於 HSF2 與 Dubbo2 的歷史兩者之間有很多相似之處,但實際卻已經演進成兩個不同的框架,在實現了 Dubbo3 的融合之後,阿里巴巴正在完全用開源 Dubbo3 取代 HSF2;在此,有些朋友可能會問,完全用開源的 Dubbo3 如何滿足阿里自身特有的訴求?答案就是通過 SPI 擴充套件,所以在阿里內部現在還有一套 HSF3,而 HSF3 與以往的 HSF2 已經完全不同了,HSF3 完全就是基於標準 Dubbo3 的 SPI 擴充套件庫,如註冊中心擴充套件、路由元件擴充套件、監控元件擴充套件等,而其他設定組裝、服務暴露、服務發現、地址解析等核心流程都是完全跑在 Dubbo3 之上;在這樣的模式下,阿里巴巴的內部實踐訴求都將完全體現在開源 Dubbo3 之上,包括內部開發人員也工作在開源 Dubbo3 之上。通過 SPI 擴充套件,同樣也適用於公有云產品以及其他廠商的實踐。

首先是效能、資源利用率的提升。升級 Dubbo3 的應用預期能實現單機記憶體 50% 的下降,對於越大規模的叢集效果將越明顯,Dubbo3 從架構上支援百萬範例級別的叢集橫向擴充套件,同時依賴應用級服務發現、Triple協定等可以大大提供應用的服務治理效率和吞吐量。

其次,是 Dubbo3 讓業務架構升級變得更容易、更合理。這個怎麼理解那,其中值得重點關注的就是協定,在 2.x 版本中,web、行動端與後端的通訊都要經過閘道器代理,完成協定轉換、型別對映等工作,Triple 協定讓這些變得更容易與自然;並通過流式通訊模型滿足更多的業務場景。

最後,得益於 Dubbo3 的完善雲原生解決方案,Dubbo3 可以幫助業務遮蔽底層雲原生基礎設施細節,使得業務的遷移成本更低。

接下來我們著重講解 Dubbo3 應用級服務發現的詳細方案,也就是餓了麼升級目標中最重要的一部分能力。

我們從 Dubbo 最經典的工作原理圖說起,Dubbo 從設計之初就內建了服務地址發現的能力,Provider 註冊地址到註冊中心,Consumer 通過訂閱實時獲取註冊中心的地址更新,在收到地址列表後,consumer 基於特定的負載均衡策略發起對 provider 的 RPC 呼叫。
在這個過程中

  • 每個 Provider 通過特定的 key 向註冊中心註冊本機可存取地址;
  • 註冊中心通過這個 key 對 provider 範例地址進行聚合;
  • Consumer 通過同樣的 key 從註冊中心訂閱,以便及時收到聚合後的地址列表;

這裡,我們對介面級地址發現的內部資料結構進行詳細分析。
首先,看右下角 provider 範例內部的資料與行為。Provider 部署的應用中通常會有多個 Service,也就是 Dubbo2 中的服務,每個 service 都可能會有其獨有的設定,我們所講的 service 服務釋出的過程,其實就是基於這個服務設定生成地址 URL 的過程,生成的地址資料如圖所示;同樣的,其他服務也都會生成地址。
然後,看一下注冊中心的地址資料儲存結構,註冊中心以 service 服務名為資料劃分依據,將一個服務下的所有地址資料都作為子節點進行聚合,子節點的內容就是實際可存取的ip地址,也就是我們 Dubbo 中 URL,格式就是剛才 provider 範例生成的。

我們再來看一下 URL 地址的詳細格式,這裡把 URL 地址資料劃分成了幾份:

  • 首先是範例可存取地址,主要資訊包含 ip port,是消費端將基於這條資料生成 tcp 網路連結,作為後續 RPC 資料的傳輸載體
  • 其次是 RPC 後設資料,後設資料用於定義和描述一次 RPC 請求,一方面表明這條地址資料是與某條具體的 RPC 服務有關的,它的版本號、分組以及方法相關資訊,另一方面表明
  • 下一部分是 RPC 設定資料,部分設定用於控制 RPC 呼叫的行為,還有一部分設定用於同步 Provider 程序範例的狀態,典型的如超時時間、資料編碼的序列化方式等。
  • 最後一部分是自定義的後設資料,這部分內容區別於以上框架預定義的各項設定,給了使用者更大的靈活性,使用者可任意擴充套件並新增自定義後設資料,以進一步豐富範例狀態。

結合以上兩頁對於 Dubbo2 介面級地址模型的分析,以及最開始的 Dubbo 基本原理圖,我們可以得出這麼幾條結論:

  • 第一,地址發現聚合的 key 就是 RPC 粒度的服務
  • 第二,註冊中心同步的資料不止包含地址,還包含了各種後設資料以及設定
  • 得益於 1 與 2,Dubbo 實現了支援應用、RPC 服務、方法粒度的服務治理能力

這就是一直以來 Dubbo2 在易用性、服務治理功能性、可延伸性上強於很多服務架構的真正原因。

一個事物總是有其兩面性,Dubbo2 地址模型帶來易用性和強大功能的同時,也給整個架構的水平可延伸性帶來了一些限制。這個問題在普通規模的微服務叢集下是完全感知不到的,而隨著叢集規模的增長,當整個叢集內應用、機器達到一定數量時,整個叢集內的各個元件才開始遇到規模瓶頸。在總結包括阿里巴巴、工商銀行等多個典型的使用者在生產環境特點後,我們總結出以下兩點突出問題(如圖中紅色所示):

  • 首先,註冊中心叢集容量達到上限閾值。由於所有的 URL 地址資料都被傳送到註冊中心,註冊中心的儲存容量達到上限,推播效率也隨之下降。
  • 而在消費端這一側,Dubbo2 框架常駐記憶體已超 40%,每次地址推播帶來的 cpu 等資源消耗率也非常高,影響正常的業務呼叫。

為什麼會出現這個問題?我們以一個具體 provider 範例進行展開,來嘗試說明為何應用在介面級地址模型下容易遇到容量問題。
青藍色部分,假設這裡有一個普通的 Dubbo Provider 應用,該應用內部定義有 10 個 RPC Service,應用被部署在 100 個機器範例上。這個應用在叢集中產生的資料量將會是 「Service 數 * 機器範例數」,也就是 10 * 100 = 1000 條。資料被從兩個維度放大:

  • 從地址角度。100 條唯一的範例地址,被放大 10 倍
  • 從服務角度。10 條唯一的服務後設資料,被放大 100 倍

面對這個問題,在 Dubbo3 架構下,我們不得不重新思考兩個問題:

  • 如何在保留易用性、功能性的同時,重新組織 URL 地址資料,避免冗餘資料的出現,讓 Dubbo3 能支撐更大規模叢集水平擴容?
  • 如何在地址發現層面與其他的微服務體系如 Kubernetes、Spring Cloud 打通?

Dubbo3 的應用級服務發現方案設計本質上就是圍繞以上兩個問題展開。其基本思路是:地址發現鏈路上的聚合元素也就是我們之前提到的 Key 由服務調整為應用,這也是其名稱叫做應用級服務發現的由來;另外,通過註冊中心同步的資料內容上做了大幅精簡,只保留最核心的 ip、port 地址資料。

這是升級之後應用級地址發現的內部資料結構進行詳細分析。
對比之前介面級的地址發現模型,我們主要關注橙色部分的變化。首先,在 provider 範例這一側,相比於之前每個 RPC Service 註冊一條地址資料,一個 provider 範例只會註冊一條地址到註冊中心;而在註冊中心這一側,地址以應用名為粒度做聚合,應用名節點下是精簡過後的 provider 範例地址;

應用級服務發現的上述調整,同時實現了地址單條資料大小和總數量的下降,但同時也帶來了新的挑戰:我們之前 Dubbo2 強調的易用性和功能性的基礎損失了,因為後設資料的傳輸被精簡掉了,如何精細的控制單個服務的行為變得無法實現。
針對這個問題,Dubbo3 的解法是引入一個內建的 MetadataService 後設資料服務,由中心化推播轉為 Consumer 到 Provider 的對等拉取,在這個模式下,後設資料傳輸的資料量將不在是一個問題,因此可以在後設資料中擴充套件出更多的引數、暴露更多的治理資料。

這裡我們個重點看消費端 Consumer 的地址訂閱行為,消費端從分兩步讀取地址資料,首先是從註冊中心收到精簡後的地址,隨後通過呼叫 MetadataService 後設資料服務,讀取對端的後設資料資訊。在收到這兩部分資料之後,消費端會完成地址資料的聚合,最終在執行態還原出類似 Dubbo2 的 URL 地址格式。因此從最終結果而言,應用級地址模型同時兼顧了地址傳輸層面的效能與執行層面的功能性。

以上就是的應用級服務發現背景、工作原理部分的所有內容,接下來我們看一下餓了麼升級到 Dubbo3 尤其是應用級服務發現的過程。

這裡是餓了麼的的基本部署架構圖。在升級之前,餓了麼的微服務架構採用的是 HSF2,跨單元的 RPC 呼叫是通過 proxy 中轉代理,在這個過程中 proxy 所承載的機器數和流量迅速增長,比較突出的一點是 proxy 在訂閱所有的地址資料後資源消耗和穩定性都收到嚴峻挑戰。
通過全站升級 Dubbo3,業務線期望達到兩個目標:

  • 將地址模型切換到應用級服務發現大幅減輕中心化節點和消費端節點的資源消耗壓力。
  • 以應用級服務發現架構下的全域性共用註冊中心取代 proxy 模式,實現跨單元節點通訊直連。

不論是針對 Dubbo2 還是 HSF2,我們都做了全面的 API 相容,因此 Dubbo3 基本可以做到零改造升級,並且每個應用都是獨立透明升級,不需要關心它的上下游應用的升級狀態,因為 Dubbo3 升級之後不論是從地址發現模型還是協定的預設行為都保持與 2.0 版本相容,使用者可以在任意時間點對任意應用按需切換 Dubbo3 行為。
如右圖所示,我們模擬展示了餓了麼叢集 Dubbo3 升級過程的一箇中間狀態,其中灰色標記的是老版本 HSF2 應用,橙色和綠色標記的是已經升級 Dubbo3 的應用,橙色部分的應用及其呼叫鏈路代表不但已經升級到 Dubbo3,同時也完成了 Dubbo3 行為的切換,在這裡是指已經切換到了應用級地址模型。這裡的升級過程主要為了說明 Dubbo3 框架升級的相容性和獨立性。

接下來,我們詳細分析一下橙色部分節點往 Dubbo3 應用級發現遷移的具體過程

首先看 Provider 側,服務提供者在升級 Dubbo3 後會預設保持雙註冊行為,即同時註冊介面級地址和應用級地址到註冊中心,一方面保持相容,另一方面為未來消費端遷移做好準備。雙註冊的開關可通過 -Ddubbo.application.register-mode=al/interface/interface控制,我們推薦保持雙註冊的預設行為以減少後續遷移成本。
大家可能擔心雙註冊給註冊中心帶來的儲存壓力,實際上在應用級服務發現模型下這並不是一個問題,因為大家如果回想前面我們對應用級服務發現工作原理的分析,註冊地址已經被大幅精簡,根據我們實際推算,每多註冊一條應用級服務發現 URL 地址,只會增加 0.1% ~ 1% 的額外開銷。

與提供端類似,要實現平滑遷移消費端也要經歷雙訂閱的過程,流程上就不再贅述。消費端的雙訂閱行為也可通過規則或開關進行動態調整,控制消費端的消費的某個服務、應用遷移到應用級地址模型;除此之外,Dubbo3 還內建了自動決策機制,在發現應用級地址可用的情況下即會自動完成切換,並且這個行為是預設的。

餓了麼成功升級 Dubbo3 及應用級服務發現模型,實現了去 proxy 架構的目標,在我們關心的服務發現資料鏈路上:

  • 資料註冊與訂閱的傳輸量下降 90%
  • 註冊中心資料儲存的總體資源佔用下降 90%
  • 消費端服務架構自身的常駐記憶體消耗下降達 50%

叢集總體的穩定性、效能都得到明顯提升,也為未來容量擴充套件做好準備。

雖然餓了麼的整體部署架構比較複雜,但我們對餓了麼的 Dubbo3 升級過程的講解還是非常簡單直接的,因為服務發現的過程本身就是比較簡單的,核心就是圍繞提供者、消費者、註冊中心三個節點的資料同步。其中重要的是三點,一個是對於應用級服務發現工作原理的整體講解,第二點是 Dubbo3 的基本升級過程,Dubbo3 可以實現透明相容升級,按需切換行為,第三點是 Dubbo3 在餓了麼為代表的阿里巴巴內部真正意義上的實現了對 HSF2 的替換,除了個別 SPI 擴充套件實現了與開源版本保持了一致。

搜尋關注官方微信公眾號:Apache Dubbo,瞭解更多業界最新動態,掌握大廠面試必備 Dubbo 技能