掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
作者|vivo 互聯(lián)網(wǎng)中間件團(tuán)隊(duì)- Liu Runyun

大量業(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)行替換。本文將介紹基于RocketMQ建設(shè)消息中間件平臺(tái)并實(shí)現(xiàn)在線業(yè)務(wù)無(wú)感知的平滑遷移。
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)題:
架構(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)題。
業(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ù)。
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)消息軌跡功能。
基于以上問(wèn)題,中間件團(tuán)隊(duì)于2020年Q4開(kāi)始進(jìn)行了下一代消息中間件平臺(tái)方案的調(diào)研,為保證下一代消息中間件平臺(tái)符合業(yè)務(wù)新的需求,我們首先明確了消息中間件平臺(tái)的建設(shè)目標(biā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ì)比:
Pulsar部署架構(gòu)(來(lái)源:Pulsar社區(qū))
RocketMQ部署架構(gòu)(來(lái)源:RocketMQ社區(qū))
Pulsar:
RocketMQ:
Pulsar
RocketMQ
Pulsar
RocketMQ
從高可用架構(gòu)分析,Pulsar基于Bookeeper組件實(shí)現(xiàn)了架構(gòu)的計(jì)算與存儲(chǔ)分離,可以實(shí)現(xiàn)故障的快速恢復(fù);RocketMQ采用了主從復(fù)制的架構(gòu),故障恢復(fù)依賴(lài)主從切換。
從功能特性分析,Pulsar支持了豐富的過(guò)期策略,支持了消息去重,可以支持實(shí)時(shí)計(jì)算中消息只消費(fèi)一次的語(yǔ)義;RocketMQ在事務(wù)消息、消息軌跡、消費(fèi)模式等特性對(duì)在線業(yè)務(wù)有更好的支持。
從這兩方面對(duì)比,最終選擇了RocketMQ構(gòu)建我們下一代的消息中間件平臺(tái)。
通過(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)需要完成:
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)高效的、互不干擾的消息推送,有以下策略:
最終選擇了第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)ack/uack后再次通過(guò)信號(hào)量通知下一次推送,這樣也保證了使用少量的線程資源即可完成海量消息的推送需求。
基于消息網(wǎng)關(guān),可以在消息推送邏輯中增加消費(fèi)啟停和消費(fèi)限流邏輯。
消費(fèi)啟??梢詭椭鷺I(yè)務(wù)快速實(shí)現(xiàn)消費(fèi)的暫停或是部分異常節(jié)點(diǎn)停止消息消費(fèi)。
消費(fèi)限流可以幫助業(yè)務(wù)控制消息消費(fèi)速率,避免對(duì)底層依賴(lài)產(chǎn)生太大壓力。
原生RabbitMQ集群業(yè)務(wù)壓測(cè)性能
使用消息網(wǎng)關(guān)后業(yè)務(wù)壓測(cè)性能
業(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),中間件團(tuán)隊(duì)計(jì)劃在三個(gè)方面對(duì)消息中間件進(jìn)行迭代演進(jìn):

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流