從RabbitMQ平滑遷移到RocketMQ技術實戰
作者:vivo 網際網路中介軟體團隊- Liu Runyun
大量業務使用訊息中介軟體進行系統間的解耦、非同步化、削峰填谷設計實現。公司內部前期基於RabbitMQ實現了一套高可用的訊息中介軟體平臺。隨著業務的持續增長,訊息體量隨之增大,對訊息中介軟體平臺提出了更高的要求,此外在運維過程中也遇到了高可用難以保障,功能特性不足等諸多問題。基於遇到的這些問題,決定引入RocketMQ進行替換。本文將介紹基於RocketMQ建設訊息中介軟體平臺並實現線上業務無感知的平滑遷移。
一、背景說明
vivo網際網路中介軟體團隊於2016年開始基於開源RabbitMQ向業務提供高可用訊息中介軟體平臺服務。
為解決好業務流量快速增長的問題,我們透過合理的業務叢集拆分和動態調整, 較好的交付了業務對訊息中介軟體平臺的 平臺能力需求。
但是隨著業務長週期的迅猛發展,訊息體量也越來越大,在高併發、大流量場景下RabbitMQ的系統架構設計存在著一定的限制,主要有以下問題:
1.1 高可用能力不足
架構設計存在腦裂風險,並且預設腦裂後無法自動恢復,人工介入恢復存在資料丟失的風險。
為解決腦裂問題,可以選擇將網路異常後的處理調整為pause_minority模式,但是也帶來了可能微小的網路抖動也會導致叢集故障無法恢復的問題。
1.2. 效能不足
業務訊息傳送後透過exchange路由到對應的queue中,每一個queue由叢集中的某個節點實際承載流量,高流量下叢集中的某個節點可能會成為瓶頸。
queue由某個節點承載流量後無法快速遷移,強制遷移到其它低負載節點可能會導致queue不可用,這也導致了向叢集中新增節點並無法快速提升叢集的流量承載能力。
叢集效能較低,經測試使用三臺機器組成叢集,可承載大概數萬tps左右,並且由於queue是由叢集中某個節點實際承載的,也無法繼續提升某個queue的效能,這樣就無法支撐大流量業務。
訊息堆積到千萬或更多後會導致叢集效能下降,甚至海量堆積後如果消費請求tps特別高,可能會因為磁碟的效能損耗導致傳送效能下降,並且在訊息堆積太多時恢復時間長甚至無法恢復。
1.3 功能特性不足
RabbitMQ 預設情況下消費異常會執行立即重新投遞,少量的異常訊息也可能導致業務無法消費後續訊息。
功能特性上未支援事務訊息、順序訊息功能。
雖可自行實現訊息軌跡邏輯,但是會對叢集產生非常大的效能損耗,在正式環境中實際無法基於RabbitMQ原生的能力實現訊息軌跡功能。
二、訊息中介軟體平臺的專案目標
基於以上問題,中介軟體團隊於2020年Q4開始進行了下一代訊息中介軟體平臺方案的調研,為保證下一代訊息中介軟體平臺符合業務新的需求,我們首先明確了訊息中介軟體平臺的建設目標,主要包含兩部分:
-
業務需求
-
平臺需求
2.1 業務需求分析
高效能:可支撐極高的tps,並且支援水平擴充套件,可快速滿足業務的流量增長需求,訊息中介軟體不應成為業務請求鏈路效能提升的瓶頸點。
高可用:極高的平臺可用性(>99.99%),極高的資料可靠性(>99.99999999%)。
豐富的功能特性:支援叢集、廣播消費;支援事務訊息、順序訊息、延時訊息、死信訊息;支援訊息軌跡。
2.2 平臺運維需求分析
-
可運維:業務使用許可權校驗;業務生產消費流量限制;業務流量隔離與快速遷移能力。
-
可觀測:豐富的效能指標觀察叢集的執行情況。
-
可掌握:可基於開源元件快速進行二次開發,豐富平臺功能特性和進行相關問題修復。
-
雲原生:後續可基於容器化提供雲原生訊息中介軟體,提供更高的彈性和可伸縮能力。
-
總結:需要建設高效能、高可靠的下一代訊息中介軟體,具備極高的資料可靠性,豐富的功能特性,並且需要完美相容當前的RabbitMQ平臺,幫助業務快速遷移到新訊息中介軟體平臺,減少業務遷移成本。
三、開源元件選型調研
基於當前RabbitMQ平臺的問題和對下一代訊息中介軟體平臺的專案需求,我們開展了針對當前較流行的兩款訊息中介軟體:RocketMQ、Pulsar的調研。
調研過程中主要針對以下兩方面進行對比:
3.1 高可用能力分析對比
3.1.1 高可用架構與負載均衡能力對比
Pulsar部署架構(來源: )
RocketMQ部署架構(來源: )
-
Pulsar:
採用計算與儲存分離架構設計,可以實現海量資料儲存,並且支援冷熱資料分離儲存。
基於ZK和Manager節點控制Broker的故障切換以實現高可用。
Zookeeper採用分層分片儲存設計,天然支援負載均衡。
-
RocketMQ:
採用存算一體架構設計,主從模式部署,master節點異常不影響訊息讀取,Topic採用分片設計。
需要二次開發支援主從切換實現高可用。
未實現Broker的自動負載均衡,可以將top n流量Topic分佈到不同的Broker中實現簡單的負載均衡。
3.1.2 擴縮容與故障恢復對比
-
Pulsar
Broker與BooKeeper獨立擴縮容,並且擴縮容後會完成自動負載均衡。
Broker節點無狀態,故障後承載Topic會自動轉移到其它Broker節點,完成故障秒級恢復。
BooKeeper由自動恢復服務進行ledger資料對齊,並恢復到設定的QW份。
故障期間已ack訊息不會丟失,未ack訊息需要客戶端重發。
-
RocketMQ
Broker擴縮容後需要人工介入完成Topic流量均衡,可開發自動負載均衡元件結合Topic的讀寫許可權控制自動化完成擴縮容後的負載均衡。
基於主從切換實現高可用,由於客戶端定期30秒從NameSrv更新路由,因此故障恢復時間在30~60秒,可以結合客戶端降級策略讓客戶端主動剔除異常Broker節點,實現更快故障恢復。
採用同步複製非同步刷盤部署架構,在極端情況下會造成少量訊息丟失,採用同步複製同步刷盤,已寫入訊息不會丟失。
3.1.3 效能對比
-
Pulsar
可支撐百萬Topic數量,實際受到ZK儲存後設資料限制。
根據內部壓測1KB訊息可支撐TPS達數十萬。
-
RocketMQ
邏輯上可支撐百萬Topic,實際在達到數萬時Broker與NameSrv傳輸心跳包可能超時,建議單叢集不超過5萬。
根據壓測可支撐1KB訊息體TPS達10萬+。
3.2 功能特性對比
3.3 總結
從高可用架構分析,Pulsar基於Bookeeper元件實現了架構的計算與儲存分離,可以實現故障的快速恢復;RocketMQ採用了主從複製的架構,故障恢復依賴主從切換。
從功能特性分析,Pulsar支援了豐富的過期策略,支援了訊息去重,可以支援實時計算中訊息只消費一次的語義;RocketMQ在事務訊息、訊息軌跡、消費模式等特性對線上業務有更好的支援。
從這兩方面對比,最終選擇了 RocketMQ構建我們下一代的訊息中介軟體平臺。
四、平滑遷移建設
透過技術調研,確定了基於RocketMQ建設下一代訊息中介軟體平臺。
為了實現業務從RabbitMQ平滑遷移到RocketMQ,就 需要建設訊息閘道器實現訊息從AMQP協議轉換到RocketMQ;RabbitMQ與RocketMQ的後設資料語義與儲存存在差異,需要實現後設資料語義的對映與後設資料的獨立儲存。
主要有以下四個事項需要完成:
4.1 訊息閘道器獨立部署與嵌入式部署差異對比
4.2 後設資料定義對映與維護
4.3 互不干擾的高效能訊息推送
RabbitMQ採用推模式進行訊息消費,雖然RocketMQ也支援訊息推送消費,但是因為AMQP協議中透過prefetch引數限制了客戶端快取訊息數量以保證不會因快取太多訊息導致客戶端記憶體異常,因此在訊息閘道器實現訊息推送時也需要滿足AMQP協議的語義。
同時每個訊息閘道器都需要數千甚至數萬的queue的訊息推送,每個queue訊息消費速率存在差異,並且每個佇列可能隨時有訊息需要推送到客戶端進行消費,要保證不同queue之間的推送互不干擾且及時。
為了實現高效的、互不干擾的訊息推送,有以下策略:
每個queue採用獨立的執行緒,保證互不干擾和時效性,缺點是無法支撐海量queue的訊息推送。
基於訊號量、阻塞佇列等,在感知到有可推送訊息和可消費服務端時按需進行訊息的推送,這樣可使用少量的執行緒即可完成高效的訊息推送。
最終選擇了第2種方案,資料流轉圖如下圖所示:
一個訊息消費過程:客戶端在啟動連線到訊息閘道器後,在訊息閘道器中會構建RocketMQ推送消費客戶端例項,並且注入自定義的ConsumeMessageService例項,同時使用一個訊號量儲存客戶端允許推送的訊息數量。
當訊息從叢集側推送到訊息閘道器時,將訊息按照推送的批次封裝為一個任務儲存在ConsumeMessageService例項的BlockingQueue中,同時推送執行緒會輪詢所有的ConsumeMessageService例項,如果發現本地快取有待消費的訊息並且有可消費訊息的業務客戶端,將任務提交到執行緒池中完成訊息的推送。
為了保證不會因為少量消費速率特別高的queue導致其它queue的訊息推送時效性降低,會限制每一個ConsumeMessageService只允許推送一定數量的訊息即轉到推送其它queue的訊息,以此即可保證所有queue的訊息推送的互不干擾和時效性。
在客戶端消費ack/uack後再次透過訊號量通知下一次推送,這樣也保證了使用少量的執行緒資源即可完成海量訊息的推送需求。
4.4 消費啟停與消費限流能力實現
基於訊息閘道器,可以在訊息推送邏輯中增加消費啟停和消費限流邏輯。
消費啟停可以幫助業務快速實現消費的暫停或是部分異常節點停止訊息消費。
消費限流可以幫助業務控制訊息消費速率,避免對底層依賴產生太大壓力。
4.5 平臺架構
-
最終形成了以上的平臺架構。新建設了一個AMQP-proxy訊息閘道器服務實現AMQP訊息轉換到RocketMQ,支援業務的訊息生產消費。
-
建設了mq-meta服務維護叢集的後設資料資訊。
-
透過mq-controller控制叢集的主從切換,實現叢集的高可用,同時增加了叢集監控,負載均衡模組保障叢集的高可用。
五、平臺建設進展與遷移收益
5.1 業務使用收益
5.1.1 更高、更穩定的訊息傳送效能
原生RabbitMQ叢集業務壓測效能
使用訊息閘道器後業務壓測效能
5.1.2 更豐富的功能特性
-
統一的訊息過期時間
-
消費異常訊息將按照梯度延時重投遞
-
直接支援廣播消費模式
-
全環境按需提供訊息軌跡功能
-
支援消費重置到以前的某個位點
5.1.3 業務使用特性變化
-
訊息將 不再無限期保留,預設 保留3~7天(實際保留時間根據叢集配置決定)
-
消費異常將不再立即重投遞,將按照一定的 梯度延時重投遞,多次異常後將變為死信訊息
-
直接支援 廣播消費,注意廣播消費模式消費無異常重投遞,每個訊息每個節點只消費一次
-
業務生產消費效能可支援水平擴充套件
-
不支援 消費優先順序功能
-
預設 消費超時時間15分鐘,消費超時後訊息重新投遞,消費超時時間可按需調整
-
支援 消費啟停(全域性或限制部分節點消費)
-
支援 全域性消費限流
-
限制訊息體大小,當前限制為256KB,超過將直接返回失敗,後續將進行流量治理,限制傳送大訊息體業務流量
5.2 平臺運維收益
業務從RabbitMQ遷移到RocketMQ後,可支撐業務流量從萬TPS級別提升到十萬TPS級別,可支撐業務容量從數億提升至百億級別。耗用機器資源下降50%以上,運維難度和成本均大大降低,同時可以基於訊息閘道器實現更加豐富的功能特性。
六、未來展望
未來,中介軟體團隊計劃在三個方面對訊息中介軟體進行迭代演進:
-
基於訊息閘道器能力豐富現有平臺功能特性,進行業務訊息治理。
-
過去五年中介軟體團隊基於開源RabbitMQ進行了RabbitMQ的高可用建設,發現直接讓業務方使用基於開源元件的SDK接入會帶來SDK升級困難,與後端訊息中介軟體型別繫結的問題,未來我們計劃基於GPRC和訊息閘道器,實現訊息佇列引擎服務化,業務無需關心底層具體使用的開源訊息中介軟體選型。
-
調研RocketMQ5.0計算與儲存分離構架,進行訊息中介軟體架構的再升級。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69912579/viewspace-2908372/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Android技術棧(一)從Activity遷移到FragmentAndroidFragment
- 5. ActiveMQ平滑遷移到kafkaMQKafka
- 大曝光!從RabbitMQ平滑遷移至Kafka架構設計方案!MQKafka架構
- 從 Nginx 遷移到 Envoy ProxyNginx
- 從 golang flag 遷移到 cmdrGolang
- RocketMQ實戰系列從理論到實戰MQ
- 平安科技從 Oracle 遷移到 UbiSQL 的實踐OracleSQL
- 使用DynamoShake從dynamodb遷移到mongodbMongoDB
- 從mpvue遷移到uni-appVueAPP
- [譯]從 SQLite 逐步遷移到 RoomSQLiteOOM
- [譯] 從 SQLite 逐步遷移到 RoomSQLiteOOM
- EF Core從TPH遷移到TPT
- .NET平臺系列24:從.NET Framework遷移到.NET Core/.NET5的技術指南Framework
- .NET平臺系列25:從 ASP.NET 遷移到 ASP.NET Core 的技術指南ASP.NET
- Gradle指南之從Groovy遷移到KotlinGradleKotlin
- 從Hive遷移到SparkSQL,有讚的大資料實踐HiveSparkSQL大資料
- Spring Boot 從1.5遷移到2.0.5 - DZone JavaSpring BootJava
- 從eclipse遷移到idea(1 安裝篇)EclipseIdea
- 案例:微服務從Java/SpringBoot遷移到Golang微服務JavaSpring BootGolang
- 如何從 AWS CodeCommit 遷移到極狐GitLab?MITGitlab
- 從Firebase+Redis遷移到PlanetScale+MySQLRedisMySql
- 小米Kylin平滑遷移HBase實踐
- 從Helm2遷移到 Helm v3 的最佳實踐
- 從eclipse遷移到idea(2 使用習慣篇)EclipseIdea
- 從過時的 Windows 機器遷移到 LinuxWindowsLinux
- 記錄從vuecli打包庫遷移到rollup打包Vue
- 從 CRUD 遷移到事件溯源的祕訣 - eventstore事件
- 從 Newtonsoft.Json 遷移到 System.Text.JsonJSON
- svn 遷移到gitGit
- RabbitMQ、RocketMQ、Kafka延遲佇列實現MQKafka佇列
- 將spfile從ASM裡遷移到檔案系統ASM
- Dcat Admin 教程 - 如何從 Laravel admin 遷移到 dcat admin?Laravel
- 如何從阿里雲ECS遷移到AWS EC2?阿里
- 如何平穩地從nacos遷移到r-nacos?
- 為何我們前端從Vue 2遷移到Svelte?前端Vue
- 從單體遷移到微服務的十二種方法微服務
- 如何從 vue-element-admin 遷移到 Fantastic-adminVueAST
- 【遷移】SqlServer 遷移到 MySQL 方法ServerMySql