作者 | 林清山
Apache RocketMQ 自 2012 年開源以來,因其架構(gòu)簡單、業(yè)務(wù)功能豐富、具備極強的可擴展性等特點被廣泛采用。RocketMQ 在阿里巴巴集團內(nèi)部有著數(shù)千臺的集群規(guī)模,每天十萬億消息流轉(zhuǎn)的規(guī)模。在阿里云上,RocketMQ 的商業(yè)化產(chǎn)品也以彈性云服務(wù)的形式為全球數(shù)萬個用戶提供企業(yè)級的消息解決方案,被廣泛應(yīng)用于互聯(lián)網(wǎng)、大數(shù)據(jù)、移動互聯(lián)網(wǎng)、物聯(lián)網(wǎng)等領(lǐng)域的業(yè)務(wù)場景,成為了業(yè)務(wù)開發(fā)的首選消息中間件。 盡管消息中間件 RocketMQ 在阿里巴巴和開源社區(qū)已經(jīng)走過了十多個年頭,但在云原生浩浩蕩蕩的浪潮下,我們開始對 RocketMQ 的架構(gòu)有了一些新的思考。
痛點與困局
阿里巴巴有大規(guī)模實踐 RocketMQ 的生產(chǎn)經(jīng)驗,自 RocketMQ 從 2016 年對外商業(yè)化以來,一直延續(xù)跟集團消息中間件相同的架構(gòu)為云上的客戶提供全托管的消息服務(wù),發(fā)展至今,消息隊列 RocketMQ 在云上已經(jīng)具備相當(dāng)大的業(yè)務(wù)規(guī)模。隨著業(yè)務(wù)的發(fā)展,這套極簡的分布式架構(gòu)在云原生環(huán)境下逐漸顯露出了一些不足,比如,運維成本增加、效率降低。

集團消息中間件通過存儲計算一體化的部署架構(gòu),為集團電商業(yè)務(wù)提供了高性能、低延遲、低成本的消息服務(wù)。隨著云的進化,云開始變得更加彈性,網(wǎng)絡(luò)環(huán)境更加復(fù)雜,云原生時代對效率也有了更高的要求,我們也迎來了對云上消息架構(gòu)進行云原生化改造的契機。 上圖是目前RocketMQ在云上部署的一個簡化版架構(gòu)(僅包含最核心的組件),這套部署架構(gòu)近年來在云上遇到的主要痛點有以下幾點:
1.富客戶端形態(tài)
RocketMQ 的用戶需要借助官方提供的 SDK 使用云上的服務(wù),這是一個比較重量級的富客戶端,提供了諸如順序消費、廣播消費、消費者負載均衡、消息緩存、消息重試、位點管理、推拉結(jié)合、流控、診斷、故障轉(zhuǎn)移、異常節(jié)點隔離等一系列企業(yè)級特性。RocketMQ 的富客戶端極大地降低了集團內(nèi)客戶的接入成本,一站式助力集團客戶構(gòu)建高韌性、高性能的消息驅(qū)動應(yīng)用,但云上的富客戶端有一些不足:
- 富客戶端跟云原生的技術(shù)棧不匹配,比如很難跟 Service Mesh 結(jié)合,也跟 Dapr 這類新興的云原生應(yīng)用框架不兼容(?),消費者物理資源耗費比較大,對 Serverless 彈性也不是很友好;
- 多語言客戶端對齊困難,在云上對多語言的訴求是非常強烈的,但富客戶端邏輯復(fù)雜,團隊無充足的人力保障多語言客戶端的質(zhì)量,為此云上誕生了基于 GraalVM 和 HTTP 協(xié)議的多語言 SDK,但都有其局限性;
- 客戶端不是完全無狀態(tài),存在內(nèi)存狀態(tài),重啟的時候會觸發(fā)重平衡,導(dǎo)致消費抖動、延遲。這種重平衡的設(shè)計滿足了性能上的需求,但對于敏感型業(yè)務(wù),這些抖動可以說在過去幾年貢獻了很多的工單;
- 分區(qū)級別的消費粒度,客戶端負載均衡的粒度在分區(qū),一個分區(qū)無法同時被多個消費者消費,在慢消費者場景影響非常大,無法通過擴容分擔(dān)慢消費者的壓力。
2.計算存儲一體化
Broker 是 RocketMQ 最核心的節(jié)點,承擔(dān)了服務(wù)端所有的計算和存儲邏輯,其核心能力為:
- 計算:鑒權(quán)與簽名、商業(yè)化計量、資源管理、客戶端連接管理、消費者管控治理、客戶端 RPC 處理、消息編解碼處理等。
- 存儲:基于分區(qū)的 WAL 存儲,多類型索引(普通、定時、事務(wù)等),核心的收、發(fā)、查詢能力,多副本復(fù)制能力等。
計算存儲一體化的 Broker 具備以下優(yōu)點:部署結(jié)構(gòu)簡單、開源用戶可以開箱即用;部署節(jié)點少,低成本支持集團雙十一萬億級的消息規(guī)模;數(shù)據(jù)就近處理,無中間環(huán)節(jié),性能高,延遲低。但一體化的 Broker 在云環(huán)境也有其局限性:
- 業(yè)務(wù)迭代效率低:發(fā)布單元為 Broker,即使調(diào)整了一行計量邏輯,需要全量發(fā)布數(shù)千臺 Broker 節(jié)點才能全網(wǎng)生效,導(dǎo)致業(yè)務(wù)創(chuàng)新和迭代的速度慢。
- 穩(wěn)定性風(fēng)險高:計算存儲一體,但大多數(shù)業(yè)務(wù)需求都是針對計算邏輯,存儲節(jié)點相對穩(wěn)定,頻繁的低價值發(fā)布帶來了穩(wěn)定性風(fēng)險和運維成本;每一次因計算邏輯的修改帶來的發(fā)布將引起緩存重建、消費延遲、客戶端異常感知等問題。
- 資源利用率低:Broker 是磁盤 IO 和內(nèi)存密集型應(yīng)用,對計算資源的消耗相對較低,但兩者一體后擴縮容也是一體的,無法將計算和存儲節(jié)點單獨做 Serverless 彈性,整體 Broker 集群資源利用率偏低。
管控鏈路復(fù)雜:因為數(shù)據(jù)和狀態(tài)完全分布式存儲在 Broker 上,管控節(jié)點需要與每個 Broker 進行通信,比如一個查詢操作需要命中多個 Broker 并將結(jié)果進行聚合等,導(dǎo)致管控鏈路的邏輯復(fù)雜。
3.客戶端與Broker直連
RocketMQ 當(dāng)前的用戶通過客戶端直接與 Broker 進行通信,鏈路是最短化的,運維簡單、延遲低,但這樣的設(shè)計無法很靈活地適配網(wǎng)絡(luò)極其復(fù)雜的云環(huán)境,網(wǎng)絡(luò)上有經(jīng)典網(wǎng)絡(luò)、VPC 網(wǎng)絡(luò)、公網(wǎng),部署環(huán)境上有 OXS 區(qū)、售賣區(qū),為客戶暴露每一個 Broker 節(jié)點帶來了運維上的負擔(dān):
- Broker 對客戶端不透明,客戶端感知每個 Broker 節(jié)點,Broker 的運維動作在客戶端往往有明顯的感知;
- Broker 直接對外提供服務(wù),需要為每個 Broker 申請 VIP,包含 Classic VIP、VPC VIP 甚至公網(wǎng) IP,線上運維了數(shù)千個 VIP。每個 Broker 數(shù)個 VIP,運維代價高的同時,很長一段時間 VIP 的手動申請阻礙了RocketMQ的自動化部署。
- 無法支持多接入點,Broker 通過 NameServer 暴露給用戶,只能暴露一個接入點,用戶一般只能在經(jīng)典網(wǎng)絡(luò)、VPC 網(wǎng)絡(luò)以及公網(wǎng)接入點中三選一。
基于這個大背景,阿里云消息團隊對 RocketMQ 在云上進行了云原生架構(gòu)升級專項,實踐存儲計算分離的新架構(gòu),同時引入基于gRPC 的全新多語言解決方案,來加速消息中間件的云原生化。
存算分離新思路
如何在云上實踐存算分離,如何探索出一個適合 RocketMQ 三位一體的新架構(gòu),是 RocketMQ 進行云原生架構(gòu)升級主要考慮的點,這里面有很多現(xiàn)實因素的考量:
- RocketMQ 在阿里集團已經(jīng)充分驗證了其架構(gòu)優(yōu)秀的特征,是否需要適配云的需求進行存算分離?由此帶來的延遲、額外的成本是否能覆蓋新架構(gòu)帶來的新價值?
- 阿里云上多款消息產(chǎn)品已經(jīng)是存算分離的架構(gòu)形態(tài),比如消息隊列 RabbitMQ、消息服務(wù) MNS,新的架構(gòu)怎么與這些產(chǎn)品架構(gòu)進行融合?
對于第一個問題,實踐的結(jié)果已經(jīng)告訴我們架構(gòu)簡單的優(yōu)異性,但在云上遇到的痛點又告訴我們存算分離勢在必行,可見存儲與計算要不要分離,并不是一個非此即彼的選擇,架構(gòu)上的選擇是否能都要呢?對于這個問題,我們的解法是存儲計算需要做到可分可合:
- 「分」有兩層解釋,首先代表了模塊和職責(zé)的分明,屬于計算的邏輯應(yīng)該封閉在計算模塊,屬于存儲的邏輯應(yīng)該下成到存儲模塊;第二層是計算和存儲要支持分開部署,計算完全采用無狀態(tài)的部署方式,存儲是有狀態(tài)的放式,來很好地解決在云上多租戶場景面臨的種種問題。
- 「合」的前提是從代碼設(shè)計上要先分開,至于是分開部署還是合并部署完全是業(yè)務(wù)的選擇,新的架構(gòu)必須要支持合并的部署形態(tài),滿足吞吐型的業(yè)務(wù)場景。比如,阿里集團內(nèi)部超大規(guī)模的消息流場景;又比如小規(guī)模單租戶場景,不需要服務(wù)化的場景,合并部署可以快速將 RocketMQ 投產(chǎn)。
對于第二個問題,在阿里云上有多個自研的不同協(xié)議標準的消息服務(wù),如何通過單一架構(gòu)支持多產(chǎn)品形態(tài)至關(guān)重要,將 RocketMQ 的核心業(yè)務(wù)消息的能力無縫復(fù)制到多個產(chǎn)品,放大業(yè)務(wù)價值。
總而言之,架構(gòu)層面的核心理念是以存儲計算架構(gòu)分離為切入點,進一步探索單一架構(gòu)多產(chǎn)品形態(tài),以降低消息子產(chǎn)品的重復(fù)建設(shè),最終也需要實現(xiàn)存儲與計算可分可合的部署形態(tài),同時滿足云上的運維靈活性以及開源、集團等部署簡單、高性能的需求。
1.存儲計算分離架構(gòu)
RocketMQ 5.0 在架構(gòu)上的第一個升級便是存儲計算分離改造,通過引入無狀態(tài)的 Proxy 集群來承擔(dān)計算職責(zé),原Broker 節(jié)點會逐步演化為以存儲為核心的有狀態(tài)集群,同時會重新研發(fā)一批多語言的瘦客戶端來解決富客戶端帶來的諸多問題。

上圖是一個存儲計算分離架構(gòu)的簡圖,圖中借用了 Service Mesh 關(guān)于控制和數(shù)據(jù)面的劃分思想以及 xDS 的概念來描述,架構(gòu)中各個組件的職責(zé)分別為:
- 多語言瘦客戶端,基于 gRPC 協(xié)議重新打造的一批多語言客戶端,采取 gRPC 的主要考慮其在云原生時代的標準性、兼容性以及多語言傳輸層代碼的生成能力。
- 導(dǎo)航服務(wù)(Navigation Server),通過 LB Group 暴露給客戶端,客戶端通過導(dǎo)航服務(wù)獲取數(shù)據(jù)面的接入點信息(Endpoint),隨后通過計算集群 Proxy 的 LB Group 進行消息的收發(fā)。通過 EDS 來暴露 Proxy 的接入點信息與通過 DNS 解析的負載均衡進行路由相比而言,可以作出更智能與更精細的租戶及流量控制、負載均衡決策等。
- NameServer,RocketMQ 中原有的核心組件,主要提供用于存儲的 Broker 集群發(fā)現(xiàn)(CDS)、存儲單元Topic 的路由發(fā)現(xiàn)(RDS)等,為運維控制臺組件、用戶控制臺組件、計算集群 Proxy 提供xDS服務(wù)。
- Proxy,重新研發(fā)的無狀態(tài)計算集群,數(shù)據(jù)流量的入口,提供鑒權(quán)與簽名、商業(yè)化計量、資源管理、客戶端連接管理、消費者管控治理、客戶端RPC處理、消息編解碼處理、流量控制、多協(xié)議支持等。
- Broker,原 Broker 模塊的存儲部分獨立為新的存儲節(jié)點,專注提供極具競爭力的高性能、低延遲的存儲服務(wù),存儲計算分離后也更易加速存儲能力的創(chuàng)新。原 Broker 模塊的計算部分逐漸上移到 Proxy集群當(dāng)中。
- LB Group,根據(jù)用戶的需求提供 Classic VIP、VPC VIP、Internet VIP、Single Tunnel、PrivateLink 等多樣化的接入能力。
存儲計算分離帶來的額外成本主要是延遲和成本。
關(guān)于延遲,存儲和計算節(jié)點從本地方法調(diào)用轉(zhuǎn)換為遠程調(diào)用后,無可避免地增加了延遲,一般是毫秒級別,在阿里云上即使是跨 AZ 的網(wǎng)絡(luò)通信,延遲一般在 2ms 以內(nèi),這種量級的延遲增加對大多數(shù)業(yè)務(wù)來講是完全可以接受的。
- 關(guān)于成本,存算的分開,導(dǎo)致網(wǎng)絡(luò)傳輸層面,序列化和反序列化層面不可避免需要更多的 CPU 資源。但另一方面,存儲和計算一個屬于磁盤 IO、內(nèi)存密集型,一個是 CPU 密集型,拆開后可以更好地設(shè)計規(guī)格,更好地利用碎片化資源,更容易提高資源利用率,利用云的彈性能力,成本反而可以降低。
- 簡而言之,在云上環(huán)境,云服務(wù)形態(tài)的 RocketMQ 非常適合存儲計算分離架構(gòu)。
2.存儲計算合并架構(gòu)
但從本質(zhì)來講,存儲計算分離與就近計算和就近存儲的理念是沖突的。存儲計算一體化的架構(gòu)在云上帶來了困擾,本質(zhì)還是因為云上是一個多租戶的環(huán)境,存儲計算一體化在多租戶的場景下靈活性不夠。但很多場景往往都是小規(guī)格單租戶,其實更適合存儲計算一體化。
- 在開源場景,開源用戶更加期望 RocketMQ 是一款開箱即用、部署簡單的消息中間件,存儲計算分離架構(gòu)會帶來一定的復(fù)雜度,影響開源生態(tài)的建設(shè)。
- 在集團的場景,數(shù)千臺物理機的規(guī)模,存儲計算分離將帶來額外的機器成本。
- 在專有云場景,很多專有云可能節(jié)點數(shù)量有限,更傾向于采用一體化的架構(gòu)。
為了云外云內(nèi)都能統(tǒng)一技術(shù)方案,我們更加期望的一種機構(gòu)是存儲與計算可分可合的部署形態(tài),分開部署是計算節(jié)點完全無狀態(tài),運維迭代極其簡單,合并部署時更原架構(gòu)體驗保持一致。
但無論采用什么樣的部署架構(gòu),存儲和計算的分離都是一種良好的模塊化設(shè)計方式,在編程層面的分開是必須要進行的。

如上圖所示,左邊是云上一個分離部署的形態(tài),右邊是合并部署的形態(tài),合并部署時計算節(jié)點可以作為存儲節(jié)點的SideCar,采用網(wǎng)格的思想進行部署,也可以將計算和存儲揉進同一個進程進行部署。實際上,我們在實踐的過程中,通過對代碼進行充分設(shè)計,Proxy 節(jié)點可以通過構(gòu)造器構(gòu)造出「Local」和「Cluster」部署兩種形態(tài),分別對應(yīng)合并部署和分離部署的兩種架構(gòu)形態(tài)。
3.單一架構(gòu)多產(chǎn)品形態(tài)
《云原生時代消息中間件的演進路線》一文中提到,阿里云消息團隊目前有業(yè)界最豐富的消息產(chǎn)品矩陣,包括消息隊列 RocketMQ、消息隊列 Kafka、微消息隊列 MQTT、消息隊列 AMQP、消息服務(wù) MNS、事件總線EventBridge。豐富的產(chǎn)品矩陣是團隊多年來踐行多樣性和標準化演進路線的結(jié)果,所有的消息子產(chǎn)品目前都構(gòu)建在RocketMQ 存儲內(nèi)核之上,非常具備統(tǒng)一架構(gòu)的前提。

通過單一的存儲計算分離架構(gòu),支持多產(chǎn)品的業(yè)務(wù)形態(tài),是云原生消息探索的一個重要方向。這種單一架構(gòu)多產(chǎn)品形態(tài)會帶來諸多好處,比如計算節(jié)點共建,通過模型抽象支持多業(yè)務(wù)模型,多通信協(xié)議,釋放重復(fù)建設(shè)的人力。通過存儲節(jié)點并池,各產(chǎn)品打通內(nèi)部存儲節(jié)點,形成資源池合并,統(tǒng)一運維和管控,有助于降低成本、提高效率,加速存儲創(chuàng)新,孵化消息中臺。

如上圖所示,單一架構(gòu)多產(chǎn)品形態(tài)的核心先統(tǒng)一存儲和計算,并進一步統(tǒng)一管控和運維,真正做到一套架構(gòu)支撐多個云產(chǎn)品。
- 存儲集群足夠抽象,滿足通用的消息存取需求。
- 計算集群多合一,足夠的模塊化,可插拔,滿足多產(chǎn)品部署帶來不同權(quán)限體系、不同協(xié)議、不同抽象模型等的需求。
總結(jié)
目前,阿里云消息隊列 RocketMQ 實踐存儲計算徹底分離的架構(gòu)還處于第一個過渡階段,未來的路還很長,我們會投入至少 1 年的時間在公有云環(huán)境全面落地存儲計算分離架構(gòu),讓消息服務(wù)更彈性、更云原生,讓團隊提高效率,加速業(yè)務(wù)創(chuàng)新。我們期望新的架構(gòu)能穩(wěn)定服務(wù)于未來至少 5 年的業(yè)務(wù)增長,同時,存算可分可合的部署架構(gòu)也能夠非常好地支撐不同規(guī)模開源用戶的個性化需求,讓 Apache RocketMQ 開源社區(qū)能夠整體收益于存算計算可分可合架構(gòu)的新形態(tài)。























