
作者:田寄遠(yuǎn)
(資料圖)
JCQ全名JD Cloud Message Queue,是京東云自研、具有CloudNative特性的分布式消息中間件。 JCQ設(shè)計初衷即為適應(yīng)云特性的消息中間件;具有高可用、數(shù)據(jù)可靠性、副本物理隔離、服務(wù)自治、健康狀態(tài)匯報、少運維或無運維、容器部署、彈性伸縮、租戶隔離、按量付費、云賬戶體系、授權(quán)等特性。
2017年中開始開發(fā)JCQ 1.0版本,2018年11月正式GA上線對外售賣,1.0版本中Topic受限于單臺服務(wù)器限制,滿足不了用戶超大規(guī)格topic的需求。
2019年4月 JCQ 2.0 正式上線,主要新增特性是topic 擴(kuò)縮容能力、熱點Topic在Broker間的負(fù)載均衡、熱點Broker的流量轉(zhuǎn)移。
2019年7月JCQ做了一次大的架構(gòu)演進(jìn)——計算存儲分離,大版本號為JCQ 3.0, 于2019年底上線。計算存儲分離對架構(gòu)帶來了比較明顯的好處,解決了日常遇到許多的痛點問題。下文詳細(xì)介紹此次演進(jìn)帶來的好處及解決的痛點問題。
在JCQ2.0中計算模塊與存儲模塊處于同一個進(jìn)程,升級計算模塊勢必將存儲模塊一起升級。而存儲模塊重啟是比較重的動作,需要做的工作有:加載大量數(shù)據(jù)、進(jìn)行消息數(shù)據(jù)與消息索引數(shù)據(jù)比對、臟數(shù)據(jù)截斷等操作。往往修復(fù)計算模塊一個小的Bug,就需要做上述非常重的存儲模塊重啟。而在現(xiàn)實工作中,大部分升級工作都是由于計算模塊功能更新或Bugfix引起的。
為了解決這個問題, JCQ3.0將計算模塊、存儲模塊獨立部署,之間通過RPC調(diào)用。各自升級互不影響。如下圖所示:
計算節(jié)點Broker只負(fù)責(zé)生產(chǎn)消息、推送消息、鑒權(quán)、認(rèn)證、限流、擁塞控制、客戶端負(fù)載均衡等業(yè)務(wù)邏輯,屬于無狀態(tài)服務(wù)。比較輕量,升級速度快。
存儲節(jié)點Store只負(fù)責(zé)數(shù)據(jù)寫入、副本同步、數(shù)據(jù)讀取。因為業(yè)務(wù)邏輯簡單,功能穩(wěn)定后,除優(yōu)化外基本無需改動,也就無需升級。
JCQ是共享消息中間件,用戶申請的是不同規(guī)格TPS的Topic,并不感知cpu、memory、disk等硬件指標(biāo)。 所以,JCQ服務(wù)方需要考慮如何合理的使用這些硬件指標(biāo)。
JCQ是容器部署,有多種類型的組件,這些組件對硬件的需求也是多樣化的,其中對資源消耗最多的是計算模塊和存儲模塊。在JCQ2.0版本計算模塊和存儲模塊部署在一起,選擇機(jī)型時要兼顧cpu、memory、disk等指標(biāo),機(jī)型要求單一,很難與其他產(chǎn)品線混合部署。即使是同一資源池,也存在因為調(diào)度順序,造成調(diào)度失敗的情況。如一臺機(jī)器剩余資源恰好能調(diào)度一個需要大規(guī)格磁盤的A容器,但是因為B容器先被調(diào)度到這臺機(jī)器上,剩余資源就不夠創(chuàng)建一個A容器,那這臺機(jī)器上的磁盤就浪費了。
JCQ3.0后,計算節(jié)點Broker,與存儲節(jié)點Store獨立部署。這兩個組件可以各自選擇適合自己業(yè)務(wù)的機(jī)型,部署在相應(yīng)資源池中;最終,可以做到與其他產(chǎn)品混合部署,共用資源池水位,而不用獨自承擔(dān)資源水位線。
JCQ3.0中計算節(jié)點Broker是無狀態(tài)服務(wù),主從切換比較輕量,能在秒級完成故障轉(zhuǎn)移;且部署時考慮了物理設(shè)備反親和,如跨Rack、跨AZ部署。所以,可以在可用性、資源成本之間做一定的權(quán)衡;如可以使用M:1方式做高可用冷備,而不必1:1的比例高可用冷備,進(jìn)而達(dá)到節(jié)省硬件資源的目的。
JCQ 1.0 設(shè)計之初就采用Raft算法,來解決服務(wù)高可用、數(shù)據(jù)一致性的問題。Message Log與Raft Log 有很多共同的特性,如順序?qū)憽㈦S機(jī)讀、末端熱數(shù)據(jù)。所以,直接用Raft Log當(dāng)成Message Log是非常合適的。
在JCQ演進(jìn)中我們也發(fā)現(xiàn)了Raft本身的一些性能問題,如順序復(fù)制、順序commit、有的流程只能用單線程處理等限制。針對這些問題,最直接有效的辦法就是擴(kuò)展Raft的數(shù)目、擴(kuò)展單線程流程數(shù)目,在一定數(shù)量級內(nèi),并發(fā)能力隨著Raft Group數(shù)目的增長,呈線性增長關(guān)系,稱之MultiRaft,如下圖所示。
上圖中,每個StoreNode節(jié)點是一個獨立進(jìn)程,內(nèi)部有四組邏輯RaftGroup(橙色的節(jié)點為RaftGroup的Leader),各組RaftGroup之間是并行關(guān)系,可以做到Group間并行復(fù)制、并行commit。
由于大量使用了NIO,這些RaftGroup之間可以共享通信線程池,擴(kuò)充RaftGroup數(shù)目并不會帶來線程資源線性增長的問題。
在JCQ3.0中,Broker為輕量的無狀態(tài)服務(wù),在主從切換、故障恢復(fù)方面相對2.0更為輕量,本身能更快的恢復(fù)對外服務(wù)能力。
同時,Broker將Producer、Consumer的連接請求,抽象為PubTask和SubTask,后文統(tǒng)稱為Task。Task的概念非常輕量,僅描述Client與Broker的對應(yīng)關(guān)系,由元數(shù)據(jù)管理器Manager統(tǒng)一調(diào)度、管理。轉(zhuǎn)移Task只需要修改Task的內(nèi)容,客戶端重新連接新Broker即可。
一般來說,Broker的主要瓶頸在于網(wǎng)絡(luò)帶寬。Broker定期統(tǒng)計網(wǎng)絡(luò)入口流量與出口流量,并上報給管理節(jié)點Manager。Manager根據(jù)入口流量、出口流量與帶寬閾值進(jìn)行裁決,發(fā)現(xiàn)超過閾值后,通過一定策略將相應(yīng)的Task轉(zhuǎn)移到較小負(fù)載的Broker上,并通知相應(yīng)的Producer與Consumer;Producer與Consumer收到通知后,重新獲取Task的路由信息,自動重連到新的Broker繼續(xù)進(jìn)行生產(chǎn)、消費。
設(shè)想一個場景,有一個大規(guī)格的topic,創(chuàng)建了n個消費組。消費總TPS是生產(chǎn)總TPS的n倍。增加消費組,會導(dǎo)致消費總TPS線性增長。到達(dá)一定消費組規(guī)模后,單Broker由于網(wǎng)卡帶寬的原因,無法滿足這種高扇出的場景。單服務(wù)器是無法解決這個問題。
在JCQ 3.0 可以將這些不同的消費組對應(yīng)的SubTask分散到若干個Broker上,每個Broker負(fù)責(zé)一部分SubTask,單Broker從Store預(yù)讀消息,將數(shù)據(jù)推送給Consumer。這樣多個Broker共同完成所有消費組的消息流量,協(xié)作一起提供高扇出的能力。
消息中間件很大的特點是:大部分場景下,熱數(shù)據(jù)都在末端,而回溯幾天之前的消息這個功能是不常用的。所以,就有冷熱數(shù)據(jù)之分。
JCQ 計算節(jié)點設(shè)計了一層存儲抽象層Store Bridge 可以接入不同的存儲引擎,可以接入Remote Raft Cluster,或者分布式文件系統(tǒng)WOS、或者S3。甚者可以將冷數(shù)據(jù)定期從昂貴的本地盤卸載到廉價的存儲引擎上。
相對于JCQ2.0,計算節(jié)點與存儲節(jié)點之間的通信方式,由接口調(diào)用變?yōu)镽PC調(diào)用,在延遲方面會有一定損失。經(jīng)過測試,絕大部分延遲都在1ms左右,在大多數(shù)場景下 犧牲1ms左右的延遲并不會給業(yè)務(wù)帶來太大的影響。
JCQ后續(xù)會主要在多協(xié)議兼容,按需自動擴(kuò)縮容、云原生等方面演進(jìn)。
JCQ協(xié)議為私有協(xié)議,在引導(dǎo)用戶遷移方面有比較大的障礙。后續(xù)會抽離JCQ Kernel,外部提供不同的協(xié)議接入層。方便用戶從其他MQ接入JCQ。目前已兼容RocketMQ協(xié)議,SQS協(xié)議
JCQ是共享消息中間件,但缺少Serverless自動擴(kuò)縮容的特性。每逢大促,如618,雙11,服貿(mào)會等重要活動。業(yè)務(wù)方很難預(yù)估自己的業(yè)務(wù)量峰值,或者估計不足,會造成topic限流等問題。如在保證JCQ服務(wù)本身能力情況下,能做到topic靈活的自動擴(kuò)縮容,將對用戶有極大的幫助,起到真正的削峰填谷作用。
支持在kubernetes環(huán)境部署與交付,提供原生的Operator,能夠快速的部署在k8s環(huán)境中,更好的交付私有云、混合云項目。