TPS提升10倍,RabbitMQ到RocketMQ不停機(jī)平滑遷移實(shí)戰(zhàn)
大量業(yè)務(wù)使用消息中間件進(jìn)行系統(tǒng)間的解耦、異步化、削峰填谷設(shè)計(jì)實(shí)現(xiàn)。公司內(nèi)部前期基于RabbitMQ實(shí)現(xiàn)了一套高可用的消息中間件平臺(tái)。隨著業(yè)務(wù)的持續(xù)增長(zhǎng),消息體量隨之增大,對(duì)消息中間件平臺(tái)提出了更高的要求,此外在運(yùn)維過(guò)程中也遇到了高可用難以保障,功能特性不足等諸多問(wèn)題。基于遇到的這些問(wèn)題,決定引入RocketMQ進(jìn)行替換。
一、背景說(shuō)明
vivo互聯(lián)網(wǎng)中間件團(tuán)隊(duì)于2016年開(kāi)始基于開(kāi)源RabbitMQ向業(yè)務(wù)提供高可用消息中間件平臺(tái)服務(wù)。
為解決好業(yè)務(wù)流量快速增長(zhǎng)的問(wèn)題,我們通過(guò)合理的業(yè)務(wù)集群拆分和動(dòng)態(tài)調(diào)整,較好地交付了業(yè)務(wù)對(duì)消息中間件平臺(tái)的平臺(tái)能力需求。
但是隨著業(yè)務(wù)長(zhǎng)周期的迅猛發(fā)展,消息體量也越來(lái)越大,在高并發(fā)、大流量場(chǎng)景下RabbitMQ的系統(tǒng)架構(gòu)設(shè)計(jì)存在著一定的限制,主要有以下問(wèn)題:
1、高可用能力不足
架構(gòu)設(shè)計(jì)存在腦裂風(fēng)險(xiǎn),并且默認(rèn)腦裂后無(wú)法自動(dòng)恢復(fù),人工介入恢復(fù)存在數(shù)據(jù)丟失的風(fēng)險(xiǎn)。
為解決腦裂問(wèn)題,可以選擇將網(wǎng)絡(luò)異常后的處理調(diào)整為pause_minority模式,但是也帶來(lái)了可能微小的網(wǎng)絡(luò)抖動(dòng)也會(huì)導(dǎo)致集群故障無(wú)法恢復(fù)的問(wèn)題。
2、性能不足
業(yè)務(wù)消息發(fā)送后通過(guò)exchange路由到對(duì)應(yīng)的queue中,每一個(gè)queue由集群中的某個(gè)節(jié)點(diǎn)實(shí)際承載流量,高流量下集群中的某個(gè)節(jié)點(diǎn)可能會(huì)成為瓶頸。
queue由某個(gè)節(jié)點(diǎn)承載流量后無(wú)法快速遷移,強(qiáng)制遷移到其它低負(fù)載節(jié)點(diǎn)可能會(huì)導(dǎo)致queue不可用,這也導(dǎo)致了向集群中添加節(jié)點(diǎn)并無(wú)法快速提升集群的流量承載能力。
集群性能較低,經(jīng)測(cè)試使用三臺(tái)機(jī)器組成集群,可承載大概數(shù)萬(wàn)tps左右,并且由于queue是由集群中某個(gè)節(jié)點(diǎn)實(shí)際承載的,也無(wú)法繼續(xù)提升某個(gè)queue的性能,這樣就無(wú)法支撐大流量業(yè)務(wù)。
消息堆積到千萬(wàn)或更多后會(huì)導(dǎo)致集群性能下降,甚至海量堆積后如果消費(fèi)請(qǐng)求tps特別高,可能會(huì)因?yàn)榇疟P(pán)的性能損耗導(dǎo)致發(fā)送性能下降,并且在消息堆積太多時(shí)恢復(fù)時(shí)間長(zhǎng)甚至無(wú)法恢復(fù)。
3、功能特性不足
RabbitMQ 默認(rèn)情況下消費(fèi)異常會(huì)執(zhí)行立即重新投遞,少量的異常消息也可能導(dǎo)致業(yè)務(wù)無(wú)法消費(fèi)后續(xù)消息。
功能特性上未支持事務(wù)消息、順序消息功能。
雖可自行實(shí)現(xiàn)消息軌跡邏輯,但是會(huì)對(duì)集群產(chǎn)生非常大的性能損耗,在正式環(huán)境中實(shí)際無(wú)法基于RabbitMQ原生的能力實(shí)現(xiàn)消息軌跡功能。
二、消息中間件平臺(tái)的項(xiàng)目目標(biāo)
基于以上問(wèn)題,中間件團(tuán)隊(duì)于2020年Q4開(kāi)始進(jìn)行了下一代消息中間件平臺(tái)方案的調(diào)研,為保證下一代消息中間件平臺(tái)符合業(yè)務(wù)新的需求,我們首先明確了消息中間件平臺(tái)的建設(shè)目標(biāo),主要包含兩部分:
- 業(yè)務(wù)需求
- 平臺(tái)需求
1、業(yè)務(wù)需求分析
- 高性能
可支撐極高的tps,并且支持水平擴(kuò)展,可快速滿足業(yè)務(wù)的流量增長(zhǎng)需求,消息中間件不應(yīng)成為業(yè)務(wù)請(qǐng)求鏈路性能提升的瓶頸點(diǎn)。
- 高可用
極高的平臺(tái)可用性(99.99%),極高的數(shù)據(jù)可靠性(99.99999999%)。
- 豐富的功能特性
支持集群、廣播消費(fèi);支持事務(wù)消息、順序消息、延時(shí)消息、死信消息;支持消息軌跡。
2、平臺(tái)運(yùn)維需求分析
- 可運(yùn)維:業(yè)務(wù)使用權(quán)限校驗(yàn);業(yè)務(wù)生產(chǎn)消費(fèi)流量限制;業(yè)務(wù)流量隔離與快速遷移能力。
- 可觀測(cè):豐富的性能指標(biāo)觀察集群的運(yùn)行情況。
- 可掌握:可基于開(kāi)源組件快速進(jìn)行二次開(kāi)發(fā),豐富平臺(tái)功能特性和進(jìn)行相關(guān)問(wèn)題修復(fù)。
- 云原生:后續(xù)可基于容器化提供云原生消息中間件,提供更高的彈性和可伸縮能力。
總結(jié):需要建設(shè)高性能、高可靠的下一代消息中間件,具備極高的數(shù)據(jù)可靠性,豐富的功能特性,并且需要完美兼容當(dāng)前的RabbitMQ平臺(tái),幫助業(yè)務(wù)快速遷移到新消息中間件平臺(tái),減少業(yè)務(wù)遷移成本。
三、開(kāi)源組件選型調(diào)研
基于當(dāng)前RabbitMQ平臺(tái)的問(wèn)題和對(duì)下一代消息中間件平臺(tái)的項(xiàng)目需求,我們開(kāi)展了針對(duì)當(dāng)前較流行的兩款消息中間件:RocketMQ、Pulsar的調(diào)研。
調(diào)研過(guò)程中主要針對(duì)以下兩方面進(jìn)行對(duì)比:
1、高可用能力分析對(duì)比
1)高可用架構(gòu)與負(fù)載均衡能力對(duì)比
Pulsar部署架構(gòu)(來(lái)源:Pulsar社區(qū))?
RocketMQ部署架構(gòu)(來(lái)源:RocketMQ社區(qū))
① Pulsar
- 采用計(jì)算與存儲(chǔ)分離架構(gòu)設(shè)計(jì),可以實(shí)現(xiàn)海量數(shù)據(jù)存儲(chǔ),并且支持冷熱數(shù)據(jù)分離存儲(chǔ)。
- 基于ZK和Manager節(jié)點(diǎn)控制Broker的故障切換以實(shí)現(xiàn)高可用。
- Zookeeper采用分層分片存儲(chǔ)設(shè)計(jì),天然支持負(fù)載均衡。
② RocketMQ
- 采用存算一體架構(gòu)設(shè)計(jì),主從模式部署,master節(jié)點(diǎn)異常不影響消息讀取,Topic采用分片設(shè)計(jì)。
- 需要二次開(kāi)發(fā)支持主從切換實(shí)現(xiàn)高可用。
- 未實(shí)現(xiàn)Broker的自動(dòng)負(fù)載均衡,可以將top n流量Topic分布到不同的Broker中實(shí)現(xiàn)簡(jiǎn)單的負(fù)載均衡。
2)擴(kuò)縮容與故障恢復(fù)對(duì)比
① Pulsar
- Broker與BooKeeper獨(dú)立擴(kuò)縮容,并且擴(kuò)縮容后會(huì)完成自動(dòng)負(fù)載均衡。
- Broker節(jié)點(diǎn)無(wú)狀態(tài),故障后承載Topic會(huì)自動(dòng)轉(zhuǎn)移到其它Broker節(jié)點(diǎn),完成故障秒級(jí)恢復(fù)。
- BooKeeper由自動(dòng)恢復(fù)服務(wù)進(jìn)行l(wèi)edger數(shù)據(jù)對(duì)齊,并恢復(fù)到設(shè)置的QW份。
- 故障期間已a(bǔ)ck消息不會(huì)丟失,未ack消息需要客戶端重發(fā)。
② RocketMQ
- Broker擴(kuò)縮容后需要人工介入完成Topic流量均衡,可開(kāi)發(fā)自動(dòng)負(fù)載均衡組件結(jié)合Topic的讀寫(xiě)權(quán)限控制自動(dòng)化完成擴(kuò)縮容后的負(fù)載均衡。
- 基于主從切換實(shí)現(xiàn)高可用,由于客戶端定期30秒從NameSrv更新路由,因此故障恢復(fù)時(shí)間在30~60秒,可以結(jié)合客戶端降級(jí)策略讓客戶端主動(dòng)剔除異常Broker節(jié)點(diǎn),實(shí)現(xiàn)更快故障恢復(fù)。
- 采用同步復(fù)制異步刷盤(pán)部署架構(gòu),在極端情況下會(huì)造成少量消息丟失,采用同步復(fù)制同步刷盤(pán),已寫(xiě)入消息不會(huì)丟失。
3)性能對(duì)比
① Pulsar
- 可支撐百萬(wàn)Topic數(shù)量,實(shí)際受到ZK存儲(chǔ)元數(shù)據(jù)限制。
- 根據(jù)內(nèi)部壓測(cè)1KB消息可支撐TPS達(dá)數(shù)十萬(wàn)。
② RocketMQ
- 邏輯上可支撐百萬(wàn)Topic,實(shí)際在達(dá)到數(shù)萬(wàn)時(shí)Broker與NameSrv傳輸心跳包可能超時(shí),建議單集群不超過(guò)5萬(wàn)。
- 根據(jù)壓測(cè)可支撐1KB消息體TPS達(dá)10萬(wàn)+。
2、功能特性對(duì)比
3、總結(jié)
從高可用架構(gòu)分析,Pulsar基于Bookeeper組件實(shí)現(xiàn)了架構(gòu)的計(jì)算與存儲(chǔ)分離,可以實(shí)現(xiàn)故障的快速恢復(fù);RocketMQ采用了主從復(fù)制的架構(gòu),故障恢復(fù)依賴主從切換。
從功能特性分析,Pulsar支持了豐富的過(guò)期策略,支持了消息去重,可以支持實(shí)時(shí)計(jì)算中消息只消費(fèi)一次的語(yǔ)義;RocketMQ在事務(wù)消息、消息軌跡、消費(fèi)模式等特性對(duì)在線業(yè)務(wù)有更好的支持。
從這兩方面對(duì)比,最終選擇了RocketMQ構(gòu)建我們下一代的消息中間件平臺(tái)。
四、平滑遷移建設(shè)
通過(guò)技術(shù)調(diào)研,確定了基于RocketMQ建設(shè)下一代消息中間件平臺(tái)。
為了實(shí)現(xiàn)業(yè)務(wù)從RabbitMQ平滑遷移到RocketMQ,就需要建設(shè)消息網(wǎng)關(guān)實(shí)現(xiàn)消息從AMQP協(xié)議轉(zhuǎn)換到RocketMQ;RabbitMQ與RocketMQ的元數(shù)據(jù)語(yǔ)義與存儲(chǔ)存在差異,需要實(shí)現(xiàn)元數(shù)據(jù)語(yǔ)義的映射與元數(shù)據(jù)的獨(dú)立存儲(chǔ)。
主要有以下四個(gè)事項(xiàng)需要完成:
1、消息網(wǎng)關(guān)獨(dú)立部署與嵌入式部署差異對(duì)比
2、元數(shù)據(jù)定義映射與維護(hù)
3、互不干擾的高性能消息推送
RabbitMQ采用推模式進(jìn)行消息消費(fèi),雖然RocketMQ也支持消息推送消費(fèi),但是因?yàn)锳MQP協(xié)議中通過(guò)prefetch參數(shù)限制了客戶端緩存消息數(shù)量以保證不會(huì)因緩存太多消息導(dǎo)致客戶端內(nèi)存異常,因此在消息網(wǎng)關(guān)實(shí)現(xiàn)消息推送時(shí)也需要滿足AMQP協(xié)議的語(yǔ)義。
同時(shí)每個(gè)消息網(wǎng)關(guān)都需要數(shù)千甚至數(shù)萬(wàn)的queue的消息推送,每個(gè)queue消息消費(fèi)速率存在差異,并且每個(gè)隊(duì)列可能隨時(shí)有消息需要推送到客戶端進(jìn)行消費(fèi),要保證不同queue之間的推送互不干擾且及時(shí)。
為了實(shí)現(xiàn)高效的、互不干擾的消息推送,有以下策略:
- 每個(gè)queue采用獨(dú)立的線程,保證互不干擾和時(shí)效性,缺點(diǎn)是無(wú)法支撐海量queue的消息推送。
- 基于信號(hào)量、阻塞隊(duì)列等,在感知到有可推送消息和可消費(fèi)服務(wù)端時(shí)按需進(jìn)行消息的推送,這樣可使用少量的線程即可完成高效的消息推送。
最終選擇了第2種方案,數(shù)據(jù)流轉(zhuǎn)圖如下圖所示:
一個(gè)消息消費(fèi)過(guò)程:客戶端在啟動(dòng)連接到消息網(wǎng)關(guān)后,在消息網(wǎng)關(guān)中會(huì)構(gòu)建RocketMQ推送消費(fèi)客戶端實(shí)例,并且注入自定義的ConsumeMessageService實(shí)例,同時(shí)使用一個(gè)信號(hào)量保存客戶端允許推送的消息數(shù)量。
當(dāng)消息從集群側(cè)推送到消息網(wǎng)關(guān)時(shí),將消息按照推送的批次封裝為一個(gè)任務(wù)保存在ConsumeMessageService實(shí)例的BlockingQueue中,同時(shí)推送線程會(huì)輪詢所有的ConsumeMessageService實(shí)例,如果發(fā)現(xiàn)本地緩存有待消費(fèi)的消息并且有可消費(fèi)消息的業(yè)務(wù)客戶端,將任務(wù)提交到線程池中完成消息的推送。
為了保證不會(huì)因?yàn)樯倭肯M(fèi)速率特別高的queue導(dǎo)致其它queue的消息推送時(shí)效性降低,會(huì)限制每一個(gè)ConsumeMessageService只允許推送一定數(shù)量的消息即轉(zhuǎn)到推送其它queue的消息,以此即可保證所有queue的消息推送的互不干擾和時(shí)效性。
在客戶端消費(fèi)ackuack后再次通過(guò)信號(hào)量通知下一次推送,這樣也保證了使用少量的線程資源即可完成海量消息的推送需求。
4、消費(fèi)啟停與消費(fèi)限流能力實(shí)現(xiàn)
基于消息網(wǎng)關(guān),可以在消息推送邏輯中增加消費(fèi)啟停和消費(fèi)限流邏輯。
消費(fèi)啟停可以幫助業(yè)務(wù)快速實(shí)現(xiàn)消費(fèi)的暫停或是部分異常節(jié)點(diǎn)停止消息消費(fèi)。
消費(fèi)限流可以幫助業(yè)務(wù)控制消息消費(fèi)速率,避免對(duì)底層依賴產(chǎn)生太大壓力。
5、平臺(tái)架構(gòu)
- 最終形成了以上的平臺(tái)架構(gòu)。新建設(shè)了一個(gè)AMQP-proxy消息網(wǎng)關(guān)服務(wù)實(shí)現(xiàn)AMQP消息轉(zhuǎn)換到RocketMQ,支持業(yè)務(wù)的消息生產(chǎn)消費(fèi)。
- 建設(shè)了mq-meta服務(wù)維護(hù)集群的元數(shù)據(jù)信息。
- 通過(guò)mq-controller控制集群的主從切換,實(shí)現(xiàn)集群的高可用,同時(shí)增加了集群監(jiān)控,負(fù)載均衡模塊保障集群的高可用。
五、平臺(tái)建設(shè)進(jìn)展與遷移收益
1、業(yè)務(wù)使用收益
1)更高、更穩(wěn)定的消息發(fā)送性能
原生RabbitMQ集群業(yè)務(wù)壓測(cè)性能
使用消息網(wǎng)關(guān)后業(yè)務(wù)壓測(cè)性能
2)更豐富的功能特性
- 統(tǒng)一的消息過(guò)期時(shí)間;
- 消費(fèi)異常消息將按照梯度延時(shí)重投遞;
- 直接支持廣播消費(fèi)模式;
- 全環(huán)境按需提供消息軌跡功能;
- 支持消費(fèi)重置到以前的某個(gè)位點(diǎn)。
3)業(yè)務(wù)使用特性變化
- 消息將不再無(wú)限期保留,默認(rèn)保留3~7天(實(shí)際保留時(shí)間根據(jù)集群配置決定);
- 消費(fèi)異常將不再立即重投遞,將按照一定的梯度延時(shí)重投遞,多次異常后將變?yōu)樗佬畔ⅲ?/span>
- 直接支持廣播消費(fèi),注意廣播消費(fèi)模式消費(fèi)無(wú)異常重投遞,每個(gè)消息每個(gè)節(jié)點(diǎn)只消費(fèi)一次;
- 業(yè)務(wù)生產(chǎn)消費(fèi)性能可支持水平擴(kuò)展;
- 不支持消費(fèi)優(yōu)先級(jí)功能;
- 默認(rèn)消費(fèi)超時(shí)時(shí)間15分鐘,消費(fèi)超時(shí)后消息重新投遞,消費(fèi)超時(shí)時(shí)間可按需調(diào)整;
- 支持消費(fèi)啟停(全局或限制部分節(jié)點(diǎn)消費(fèi));
- 支持全局消費(fèi)限流;
- 限制消息體大小,當(dāng)前限制為256KB,超過(guò)將直接返回失敗,后續(xù)將進(jìn)行流量治理,限制發(fā)送大消息體業(yè)務(wù)流量。
2、平臺(tái)運(yùn)維收益
業(yè)務(wù)從RabbitMQ遷移到RocketMQ后,可支撐業(yè)務(wù)流量從萬(wàn)TPS級(jí)別提升到十萬(wàn)TPS級(jí)別,可支撐業(yè)務(wù)容量從數(shù)億提升至百億級(jí)別。耗用機(jī)器資源下降50%以上,運(yùn)維難度和成本均大大降低,同時(shí)可以基于消息網(wǎng)關(guān)實(shí)現(xiàn)更加豐富的功能特性。
六、未來(lái)展望
未來(lái),中間件團(tuán)隊(duì)計(jì)劃在三個(gè)方面對(duì)消息中間件進(jìn)行迭代演進(jìn):
- 基于消息網(wǎng)關(guān)能力豐富現(xiàn)有平臺(tái)功能特性,進(jìn)行業(yè)務(wù)消息治理。
- 過(guò)去五年中間件團(tuán)隊(duì)基于開(kāi)源RabbitMQ進(jìn)行了RabbitMQ的高可用建設(shè),發(fā)現(xiàn)直接讓業(yè)務(wù)方使用基于開(kāi)源組件的SDK接入會(huì)帶來(lái)SDK升級(jí)困難,與后端消息中間件類型綁定的問(wèn)題,未來(lái)我們計(jì)劃基于GPRC和消息網(wǎng)關(guān),實(shí)現(xiàn)消息隊(duì)列引擎服務(wù)化,業(yè)務(wù)無(wú)需關(guān)心底層具體使用的開(kāi)源消息中間件選型。
- 調(diào)研RocketMQ5.0計(jì)算與存儲(chǔ)分離構(gòu)架,進(jìn)行消息中間件架構(gòu)的再升級(jí)。