引言 儘管 redis 是一款非常優秀的 NoSQL 資料庫,但更重要的是,作為使用者我們應該學會在不同的場景中如何更好的使用它,更大的發揮它的價值。主要可以從這四個方面進行優化:Redis鍵值設計、批處理優化、服務端優化、集群配置優化 1. Redis慢查詢日誌使用 Redis 提供了慢日誌命令的 ...
繼業務全面上雲後,今年雙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 技能