vivo 超大規(guī)模消息中間件實踐之路
在線業(yè)務側主要從RocketMQ集群部署架構、平臺系統(tǒng)架構、日常運維操作平臺、監(jiān)控告警一體化實踐以及vivo如何通過建設AMQP消息網(wǎng)關的方式完成所有在線業(yè)務服務從RabbitMQ到RocketMQ的業(yè)務無感遷移,實現(xiàn)了在線業(yè)務消息中間件組件的統(tǒng)一。
大數(shù)據(jù)側主要從資源隔離、流量均衡、智能動態(tài)限流、集群治理四個維度介紹Kafka在vivo的最佳實踐以及Kafka核心技術架構在超大數(shù)據(jù)規(guī)模場景下的缺陷以及未來對Pulsar組件的長線規(guī)劃和建設。
一、分布式消息中間件在vivo的運營現(xiàn)狀
1.1 技術選型

在技術選型上,我們從吞吐量、功能特性、生態(tài)集成、開源活躍等多個維度對比了當前主流的分布式消息中間件,最終在線業(yè)務側我們選擇基于RocketMQ構建消息平臺,依托RocketMQ豐富的功能特性滿足業(yè)務間削峰、解耦、異步化的需求。
大數(shù)據(jù)側我們選擇具備高并發(fā)、高可用、低延遲、高吞吐能力的分布式消息中間件Kafka。構建超大數(shù)據(jù)規(guī)模處理能力的統(tǒng)一數(shù)據(jù)接入服務和實時數(shù)倉服務。Kafka組件作為統(tǒng)一數(shù)據(jù)接入服務,是大數(shù)據(jù)全鏈路中的咽喉要道,是大數(shù)據(jù)生態(tài)體系建設中不可或缺的重要組件之一。
1.2 規(guī)?,F(xiàn)狀
運營指標方面目前大數(shù)據(jù)業(yè)務側Kafka集群接入項目數(shù)百、接入規(guī)模方面Topic數(shù)量達到數(shù)萬、集群日均處理消息達數(shù)十萬億條、可用性保障99.99%、單機日均處理消息達數(shù)百億條。
在線業(yè)務側RocketMQ集群接入項目數(shù)百、接入規(guī)模方面接入數(shù)千服務、集群日均處理消息達數(shù)百億條、可用性保障100%,發(fā)送平均耗時<1ms。
二、大數(shù)據(jù)側消息中間件最佳實踐
2.1 Kafka簡介

首先我們看下Kafka的官網(wǎng)定義及發(fā)展歷史,Kafka是由Apache軟件基金會開源的一個流處理平臺,是一種高吞吐量的分布式發(fā)布訂閱消息系統(tǒng)。具有高吞吐、低延遲、高并發(fā)、高可用、高可擴等特性。
Kafka是由LinkedIn公司在2010年開源,2011年交由Apache軟件基金會進行孵化,2012年成為Apache軟件基金會的頂級開源項目。
2.2 Kafka在超大數(shù)據(jù)規(guī)模場景下面臨的挑戰(zhàn)

在超大數(shù)據(jù)規(guī)模場景下我們會面臨以下幾個問題?
- 如何規(guī)劃資源隔離保證核心業(yè)務、高優(yōu)業(yè)務、一般業(yè)務之間相互不受影響?
- 如何保證集群內部節(jié)點間流量均衡,降低單節(jié)點或部分節(jié)點流量差異太大帶來的資源浪費?
- 超大數(shù)據(jù)規(guī)模場景下如何進行限流保障集群的穩(wěn)定性并盡可能降低對業(yè)務可用性的影響?
- 集群長期運行,客戶端版本多樣,如何持續(xù)保障集群的高可用性?
下面我將從資源隔離、流量均衡、智能動態(tài)限流、集群治理四個維度和大家一起交流Kafka在vivo的最佳實踐。
2.3 資源隔離

資源隔離的核心作用在于避免業(yè)務與業(yè)務之間的相互影響,但隔離粒度、資源利用率、運維成本之間如何進行權衡,是我們需要思考的重點。隔離粒度太粗會導致隔離效果不佳,隔離粒度太細會導致資源利用率較低、運維成本增加。
那vivo在Kafka集群資源隔離上是如何平衡三者關系的呢?
首先我們根據(jù)業(yè)務屬性、業(yè)務線兩個維度進行集群維度的隔離,例如我們在集群劃分上分為了商業(yè)化專用集群,監(jiān)控專用集群,日志專用集群等。在集群維度做了機器資源的物理隔離。
同時我們在集群內部引入了資源組的概念。同一個集群內部可以包含多個資源組。每個資源組可以為多個業(yè)務提供服務。資源組與資源組之間相互獨立。
上圖中右上圖是我們沒有引入資源組概念時集群內部不同業(yè)務Topic分區(qū)的分散情況,大家可以看到業(yè)務A和業(yè)務B的Topic分區(qū)分散到集群內的所有broker上,若業(yè)務A的流量突增可能會造成業(yè)務B受到影響,右下圖是我們引入資源組概念后不同業(yè)務Topic分區(qū)的分散情況,可以看到不同業(yè)務的topic分區(qū)只會分配到自己業(yè)務所屬的資源組內,即使業(yè)務A的流量突增導致機器不可用也不會對業(yè)務B造成影響。
引入資源組概念后讓我們能在集群內部實現(xiàn)機器資源的邏輯隔離。所以我們在資源隔離方面采用了物理隔離和邏輯隔離兩種方式相結合,實現(xiàn)了在超大數(shù)據(jù)規(guī)模場景下Kafka集群的資源隔離方案。
2.4 流量均衡

流量均衡的核心作用在于充分利用集群內部資源,提升資源利用率。Kafka服務作為一個有狀態(tài)的服務,Kafka在技術架構設計上Topic分區(qū)與節(jié)點綁定,不支持分區(qū)同一副本數(shù)據(jù)在磁盤和節(jié)點維度分散存儲。對分區(qū)的讀寫請求都由分區(qū)Leader所在節(jié)點進行處理。所以Kafka集群流量均衡的本質是Topic分區(qū)的分散均衡。
在流量均衡方面我們做兩期的建設,第一期我們在分區(qū)分散均衡算法上引入機器的實時出入流量、cpu負載、磁盤存儲等指標作為負載因子生成分區(qū)遷移計劃。執(zhí)行分區(qū)遷移后達到流量均衡的目的。流量均衡一期功能上線后我們將資源組內節(jié)點間流量差異從數(shù)百兆/s降低到數(shù)十兆/s。隨著集群數(shù)據(jù)規(guī)模的持續(xù)增加,我們發(fā)現(xiàn)數(shù)十兆/s的流量差異依然會造成資源浪費。
所以在流量均衡二期功能建設上我們增加了分區(qū)分散均衡、Leader分散均衡、副本分散均衡、磁盤均衡等Kafka元數(shù)據(jù)指標作為負載因子生成Kafka分區(qū)遷移計劃,并在分區(qū)遷移執(zhí)行上增加了多種遷移提交策略。流量均衡二期功能上線后我們將資源組內節(jié)點間流量差異從數(shù)十兆/s降低到十兆以內/s。

上圖是我們流量均衡一期功能上線前后資源組內節(jié)點的流量監(jiān)控面板,可以看到一期功能上線前資源組內節(jié)點間的流量偏差在數(shù)百兆/s。一期功能上線后資源組內節(jié)點間流量偏差在數(shù)十兆/s以內,資源組內節(jié)點間流量偏差降低75%。極大提升了服務端的資源利用率。

上圖是我們流量均衡二期功能上線前后資源組內節(jié)點的入出流量監(jiān)控面板,可以看到節(jié)點間入出流量偏差從數(shù)十兆/s降低到十兆以內/s,資源組內節(jié)點間流量偏差降低80%。效果也是非常明顯。
2.5 智能動態(tài)限流

限流的本質是限制客戶端的流量突增以確保服務端的可用性。避免客戶端的流量突增導致服務端整體不可用。限流的粒度,限流閾值的設定,資源利用率、服務端穩(wěn)定性之間應該如何做權衡呢?是我們需要思考的重點。限流粒度太粗會導致限流效果不佳,當大部分業(yè)務同時流量突增會對服務端的穩(wěn)定性帶來風險。限流粒度太細服務端應對客服端流量突增能力不足,限流閾值設置太大會給服務端穩(wěn)定性帶來風險,限流閾值設置太小會導致服務端資源利用率較低。
限流方面,
- 首先我們采用多平臺聯(lián)合診斷機制根據(jù)項目實際生產(chǎn)數(shù)據(jù)情況判別是否需要進行流量調整,計算調整后的限流閾值。其中多平臺包含(JMX統(tǒng)一指標采集平臺,統(tǒng)一監(jiān)控平臺、統(tǒng)一告警平臺、Kafka集群管理平臺等)。
- 第二、智能分析Kafka集群服務資源負載情況,計算各資源剩余情況。確定是否可以進行閾值調整并結合客戶端實際生產(chǎn)數(shù)據(jù)情況計算閾值調整到多少合適。
- 第三、自動實時調整限流閾值。
通過以上三步實現(xiàn)智能動態(tài)限流方案。解決了限流粒度、限流閾值設定、資源利用率、Kafka集群可用性四者之間的平衡關系。
實現(xiàn)智能動態(tài)限流后給我們帶來以下幾點明顯的收益。

- 大大提升Kafka集群服務端應對客戶端流量突增的能力。
- 利用項目錯峰的方式進一步提升Kafka集群的資源利用率。
- 智能化自動調整項目限流閾值無需人工介入,大大降低Kafka集群在超大數(shù)據(jù)規(guī)模場景下的運維成本。
- 動態(tài)根據(jù)服務端負載情況調整項目限流閾值,盡可能減小限流對業(yè)務可用性的影響。
2.6 集群治理

Kafka集群元數(shù)據(jù)統(tǒng)一由ZooKeeper集群管理,元數(shù)據(jù)信息永久有效永不過期,元數(shù)據(jù)的下發(fā)由Kafka Controller節(jié)點統(tǒng)一下發(fā),隨著業(yè)務的不斷發(fā)展,數(shù)據(jù)規(guī)模的不斷增加,集群內部Topic的數(shù)量達到萬級,分區(qū)數(shù)量達到數(shù)十萬級。元數(shù)據(jù)治理能有效避免元數(shù)規(guī)模給Kafka集群穩(wěn)定性帶來的影響。隨著接入的服務、Kafka用戶越來越多,正確的使用Kafka 客戶端也能大大提升Kafka服務端的穩(wěn)定性和資源利用率。Kafka分區(qū)與磁盤目錄綁定,創(chuàng)建Topic、Topic分區(qū)擴容時根據(jù)Topic流量合理設置Topic分區(qū)數(shù)能有效避免單機或單盤性能瓶頸成為集群整體的性能瓶頸。
vivo在Kafka集群治理方面實現(xiàn)了節(jié)點流量偏差治理、Topic元數(shù)據(jù)治理、Topic分區(qū)數(shù)據(jù)傾斜治理、Topic超大分區(qū)治理、Topic消費延遲治理等方案為Kafka集群的高可用性保駕護航。
2.7 實踐經(jīng)驗沉淀

vivo Kafka消息中間件團隊在三年時間內,根據(jù)實際的業(yè)務場景和生產(chǎn)數(shù)據(jù)規(guī)模沉淀了較多的實踐經(jīng)驗。例如在高可用/高可擴方面實現(xiàn)了機架感知、彈性伸縮、數(shù)據(jù)壓縮等能力建設,在監(jiān)控告警方面提供了用戶限流告警、Topic流量突增告警、消費延遲告警、Leader實時監(jiān)控告警,多平臺聯(lián)合故障感知告警等能力建設。我們?yōu)镵afka集群做了很多的擴展能力建設,那解決了Kafka集群在超大數(shù)據(jù)規(guī)模場景下的所有問題了嗎?答案是否定的。
接下來我們一起看看Kafka集群在超大數(shù)據(jù)規(guī)模場景下面臨的新挑戰(zhàn)。
2.8 Kafka在超大數(shù)據(jù)規(guī)模場景下由技術架構帶來的缺陷

由Kafka架構設計所帶來的一些痛點無法通過擴展能力解決,并且Kafka架構設計上分區(qū)同一副本數(shù)據(jù)與磁盤強綁定不支持分散存儲、不支持存儲與運算分離、不支持冷熱數(shù)據(jù)分層存儲等設計缺陷在超大數(shù)據(jù)規(guī)模場景下顯得尤為明顯。所以在超大數(shù)據(jù)規(guī)模場景下Kafka集群面臨了以下幾個痛點。
- 資源利用率低。
- 無法快速響應業(yè)務增長。
- 故障恢復時間長。
- 歷史數(shù)據(jù)消費故障率高(主要體現(xiàn)在磁盤io性能上)。
2.9 大數(shù)據(jù)側分布式消息中間件未來規(guī)劃
基于以上Kafka在架構設計上的缺陷,vivo Kafka團隊于2021年開始對另一款開源分布式消息中間件Pulsar進行調研。
2.9.1 Pulsar簡介

我們看下Pulsar的官網(wǎng)定義及發(fā)展史:Pulsar 是 Apache軟件基金會的頂級開源項目,是集消息、存儲、輕量化函數(shù)式計算為一體的下一代云原生分布式消息流組件,采用了計算與存儲分離的架構設計,支持多租戶、持久化存儲、多機房跨區(qū)域數(shù)據(jù)復制,具有高并發(fā)、高吞吐、低延時、高可擴,高可用等特性。
Pulsar 誕生于2012 雅虎公司內部,2016年開源交由Apache軟件基金會進行孵化,2018年成為Apache軟件基金會頂級開源項目。
2.9.2 Pulsar核心優(yōu)勢

基于Pulsar支持存算分離,分區(qū)數(shù)據(jù)分散存儲、冷熱數(shù)據(jù)分層存儲、Broker無狀態(tài)等架構設計,讓Pulsar在超大數(shù)據(jù)規(guī)模場景下具備了資源利用率較高、快速響應業(yè)務增長、秒級故障恢復、實時流量均衡、支持海量數(shù)據(jù)存儲等明顯優(yōu)勢。
2.9.3 Pulsar未來規(guī)劃

我們對Pulsar組件的規(guī)劃分為四個階段,包含項目啟動、穩(wěn)定性建設、能力進階、穩(wěn)定運營。
目前我們處在Pulsar組件穩(wěn)定性建設階段。
2022年我們的目標是打造支持日均萬億級消息處理能力的Pulsar集群,完成分層存儲,監(jiān)控告警一體化、KoP功能平臺化等擴展能力建設。
計劃2023年打造具備日均十萬億級消息處理能力的Pulsar集群,達到行業(yè)一流水準。并完成Pulsar broker容器化部署、Pulsar生態(tài)體系建設、Pulsar Sql和Pulsar Function的應用調研等擴展能力建設。
將在2024年實現(xiàn)日均數(shù)十萬億級消息處理能力的Pulsar集群,達到行業(yè)超一流的水準。
三、在線業(yè)務側消息中間件最佳實踐
3.1 RocketMQ簡介

RocketMQ是阿里巴巴于2012年開源的低延時、高并發(fā)、高可用、高可靠的分布式消息中間件,具有海量消息堆積、高吞吐、可靠重試等特性。
RocketMQ于2012年開源,2016年進入Apache孵化,于2017年成為Apache頂級項目。
3.2 RocketMQ在vivo內部使用現(xiàn)狀

vivo中間件團隊在2021年引入RocketMQ并且完成了高可用和平臺化建設。
當前分別在多個機房部署了多個集群供業(yè)務使用,每日消息量數(shù)百億。
集群分布在多個機房,每日消息量級也不低,高可用運維保障是有難度的。
3.3 vivo基于RocketMQ的高可用保障實踐經(jīng)驗
3.3.1 集群部署架構介紹

為了更好的保障集群的高可用,我們采用了雙機房熱備的方式進行集群搭建。
我們會在兩個機房進行Broker的部署,業(yè)務Topic會默認分布在兩個機房,以此來保障在一個機房內的Broker節(jié)點異常時業(yè)務可以保持正常生產(chǎn)消費能力。
業(yè)務默認是會優(yōu)先使用本機房的節(jié)點進行生產(chǎn)消費,只有在異常時才會自動快速完成跨機房的流量切換。
同時我們構建了一個BrokerController模塊用于實現(xiàn)Broker節(jié)點的主從切換,以此保障集群容量的快速恢復。
雙機房熱備模式有哪些優(yōu)勢呢?
- 第一,消息無需跨機房復制,降低對機房專線的依賴;
- 第二,可以降低業(yè)務發(fā)送消息的延時,也可以提升業(yè)務的處理性能;
雙機房熱備模式的劣勢是每個機房的節(jié)點都需要冗余一定的buffer來支撐其它機房的節(jié)點異常時自動轉移過來的業(yè)務流量。
3.3.2 平臺系統(tǒng)架構介紹

集群雙機房熱備部署模式是消息平臺的高可用基石,在此之外我們還建設了多個平臺模塊來保障平臺的高可靠。
如上圖所示,
- mq-rebalance模塊用于支撐集群流量的自動負載均衡;
- mq-monitor模塊進行監(jiān)控指標的采集并且與vivo內部的監(jiān)控系統(tǒng)打通;
- mq-recover模塊主要用于業(yè)務流量的降級和恢復處理;
- mq-live模塊用于集群的探活。
另外我們還基于社區(qū)的connector組件建設了RabbitMQ-connector,實現(xiàn)了全球消息路由能力。
后續(xù)我們計劃建設基于gRPC協(xié)議建設通用的消息網(wǎng)關實現(xiàn)與集群的交互,以此屏蔽不同的消息中間件選型。
3.3.3 運維能力平臺化提升運維效率

主要有三點實踐:
第一,RocketMQ集群配置平臺化管理。RocketMQ集群含有較多的配置項,默認是通過節(jié)點文件管理的,在大規(guī)模集群運維過程中會存在維護困難的問題。
通過平臺化管理可以確保集群內配置統(tǒng)一,節(jié)點在啟動時從平臺中讀取到所有的配置,避免在集群部署時需要登錄到機器進行配置維護,并且我們支持了集群配置的動態(tài)生效。
第二,運維操作平臺化,例如Broker節(jié)點的流量摘除與掛載、Topic一鍵擴縮容等直接通過平臺支撐,實現(xiàn)便捷運維。
第三,集群維護平臺化,我們將集群與Broker節(jié)點的關系維護在平臺中,并且在首次部署時分配Broker節(jié)點所在集群,這樣在平臺上就有清晰的集群信息,便于我們維護管理多套集群。
3.3.4 平臺監(jiān)控告警能力建設


- 一方面,我們?yōu)槊總€集群都建設了如上圖所示的監(jiān)控大盤。
在監(jiān)控大盤中有每個集群的生產(chǎn)消費流量、業(yè)務生產(chǎn)消費統(tǒng)計、發(fā)送耗時等信息,支撐我們快速觀察集群的運行狀態(tài),方便日常巡檢。
消息中間件作為在線業(yè)務請求處理鏈路中的關鍵環(huán)節(jié),高可用尤為關鍵。監(jiān)控大盤中的發(fā)送耗時信息是我們認為觀察集群是否穩(wěn)定運行的最關鍵的指標。 - 另一方面,我們對集群構建了豐富的監(jiān)控告警能力。
如上圖所示,我們分別對主機維度、集群維度、Topic/Group維度、客戶端維度都做了監(jiān)控指標埋點上報。
通過豐富的監(jiān)控告警,我們可以及時發(fā)現(xiàn)問題并快速介入處理問題,詳細的監(jiān)控告警也可以幫助我們快速確認問題根源。
3.4 業(yè)務從RabbitMQ無感遷移到RocketMQ實戰(zhàn)經(jīng)驗
3.4.1 使用RocketMQ替換RabbitMQ根因分析

分別從可用性保障、性能、容量、功能特性對比RabbitMQ和RocketMQ。
- 可用性保障方面,RabbitMQ集群無負載均衡能力,隊列流量實際由集群內某個節(jié)點承載,存在瓶頸。其次RabbitMQ存在腦裂問題,從我們的運維經(jīng)驗看如果出現(xiàn)網(wǎng)絡故障集群通常無法自動恢復,并且可能丟失少量數(shù)據(jù)。
- 性能方面,RabbitMQ集群整體性能較低,并且不支持水平擴展。
- 容量方面,從我們的運維經(jīng)驗看,當消息堆積到千萬后,RabbitMQ性能就會有所下降。在大量消息堆積開始消費后,因為RabbitMQ的背壓流控機制,最終可能會因為集群負載過大導致發(fā)送限流深圳發(fā)送阻塞。
- 功能特性方面,RabbitMQ不支持消費異常延時重投遞功能,也不支持消息軌跡、事務消息、順序消息等特性。
而RocketMQ在可用性保障、性能、容量、功能特性方面相對于RabbitMQ都是更優(yōu)的。
- 可用性保障方面,RocketMQ采用多主多從的松耦合架構部署,主從間通過同步雙寫保障消息的可靠性和一致性。
- 性能方面,Topic可以分布在多個Broker中,實現(xiàn)水平擴容,并且RocketMQ支持從從節(jié)點拉取消息,讀寫分離的設計很好的支持了業(yè)務讀取冷數(shù)據(jù)的訴求。
- 容量方面,RocketMQ使用磁盤存儲,磁盤容量就是消息的存儲容量,利用從從節(jié)點拉取冷數(shù)據(jù)特性,海量消息堆積對消息寫入性能基本無影響。
- 功能特性方面,RocketMQ支持了消息軌跡、事務消息、順序消息等特性。
綜合分析,RocketMQ可以更好的支撐互聯(lián)網(wǎng)業(yè)務的訴求。
3.4.2 AMQP消息網(wǎng)關架構支撐實現(xiàn)無感遷移

由于當前RabbitMQ已經(jīng)有數(shù)千個服務接入,為了讓業(yè)務不修改代碼即可遷移到RocketMQ,我們建設了一個AMQP消息網(wǎng)關來實現(xiàn)MQ協(xié)議的解析和流量轉發(fā)。
如上圖所示,MQ-Proxy模塊用于解析AMQP協(xié)議,代理客戶端的生產(chǎn)消費請求。
RabbitMQ的元數(shù)據(jù)信息存在在集群中,并且與RocketMQ元數(shù)據(jù)概念存在差異,為此我們建設了MQ-Meta模塊用于維護Exchange/Queue極其綁定關系等元數(shù)據(jù)信息,并且Proxy模塊可以動態(tài)感知元數(shù)據(jù)變更。
另外,為了更好的支撐業(yè)務訴求,我們對AMQP協(xié)議進行了擴展,支持了局部有序和批量消費能力。
3.4.3 RabbitMQ和RocketMQ元數(shù)據(jù)概念映射

為了更好的整合RabbitMQ和RocketMQ,我們對它們的元數(shù)據(jù)進行了一一對應。
其中將RabbitMQ的Exchange映射為RocketMQ的Topic,Queue映射為Group,RoutingKey映射為消息頭的一個參數(shù),VirtualHost映射為Namespace。
為什么將RoutingKey映射為消息頭的一個參數(shù)而不是Tag呢?這是因為RabbitMQ的RoutingKey是有模糊匹配過濾能力的,而RocketMQ的Tag是不支持模糊匹配的。
另外我們還通過擴展使得RocketMQ也支持了RoutingKey過濾。
在經(jīng)過多輪優(yōu)化后,在1KB消息體場景下,一臺8C16G的機器在單發(fā)送下可支撐超過九萬的TPS,單推送可以支撐超過六萬TPS,性能上很好的滿足了當前業(yè)務的訴求。
3.5 在線業(yè)務消息中間件的未來規(guī)劃

主要有兩部分:
一方面,我們希望可以調研升級到RocketMQ5.0版本架構,RocketMQ5.0的存算分離架構可以更好的解決我們當前遇到的存儲瓶頸問題,Pop消費可以幫助我們實現(xiàn)更好的消費負載均衡。
我們還希望可以基于gRPC協(xié)議建設統(tǒng)一的消息網(wǎng)關能力。
另一方面,我們希望可以探索消息中間件容器化部署,提供消息中間件的快速彈性擴縮容能力,更好的支持業(yè)務需求。
四、總結
回顧vivo消息中間件演進歷史,我們完成了在線業(yè)務消息中間件從RabbitMQ遷移到RocketMQ,大數(shù)據(jù)消息中間件正在從kafka演進為使用pulsar支撐。
我們理解消息中間件將繼續(xù)朝著云原生演進,滿足業(yè)務快速增長的訴求,充分利用云的優(yōu)勢為業(yè)務提供極致的體驗。






























