RocketMQ架構(gòu)上主要分為四部分構(gòu)成:
1.Producer
消息生產(chǎn)者移必,負(fù)責(zé)生產(chǎn)消息鄙早。Producer通過MQ的負(fù)載均衡模塊選擇相應(yīng)的Broker集群隊列進(jìn)行消息投遞串远,投遞的過程支持快速失敗并且低延遲
例如,業(yè)務(wù)系統(tǒng)產(chǎn)生的日志寫入到MQ的過程萧求,就是消息生產(chǎn)的過程
RocketMQ中的消息生產(chǎn)者都是以生產(chǎn)者組(Producer Group)的形式出現(xiàn)的托享。生產(chǎn)者組是同一類生產(chǎn)者的集合斑胜,這類Producer發(fā)送相同Topic類型的消息。一個生產(chǎn)者組可以同時發(fā)送多個主題的消息嫌吠。
2.Consumer
消息消費者止潘,負(fù)責(zé)消費消息。一個消息消費者會從Broker服務(wù)器中獲取到消息辫诅,并對消息進(jìn)行相關(guān)業(yè)務(wù)處理
例如凭戴,電商平臺的業(yè)務(wù)系統(tǒng)從MQ中讀取到秒殺請求,并對頂球進(jìn)行處理的過程就是消息消費的過程炕矮。
RocketMQ中的消息消費者都是以消費者組(Consumer Group)的形式出現(xiàn)的么夫。消費者組是統(tǒng)一類消費者的集合者冤,這類Consumer消費的是同一個Topic類型的消息。消費者組使得在消息消費方法档痪,實現(xiàn)負(fù)載均衡(講一個Topic中不同的Queue平均分配給同一個Consumer Group的不同Consumer涉枫,并不是負(fù)載均衡)和容錯(一個Consumer掛了,該Consumer Group中的其他Consumer可以接著消費元Consumer消費的Queue)的目標(biāo)變得非常容易
消費者組中Consumer的數(shù)量應(yīng)小于等于Topic的Queue數(shù)量腐螟。如果超出Queue數(shù)量愿汰,則多出的Consumer將不能消費消息。
不過一個Topic類型的消息可以被多個消費者組同時消費乐纸。
注意
- 1)消費者組只能消費一個Topic的消息衬廷,不能同時消費多個Topic
- 2)一個消費者組中的消費者必須訂閱完全相同的Topic
3.Name Server
3.1介紹
NameServer是一個Broker與Topic路由的注冊中心,支持Broker的動態(tài)注冊與發(fā)現(xiàn)汽绢。
RocketMQ的思想來自于Kafuka吗跋,而Kafka是以來了Zookeeper的。所以宁昭,在RocketMQ的早期版本也依賴Zookeeper跌宛。從3.0開始去掉了Zookeeper的依賴,使用了自己的NameServer积仗。
3.2功能介紹
- Broker管理:接受Broker集群的注冊信息并保存下來作為路由信息的基本數(shù)據(jù);提供心跳檢測機制秩冈,檢查Broker是否存活
- 路由信息管理:每個NameServer中都保存著Broker集群的整個路由信息和用于客戶端查詢的隊列信息。Producer和Consumer通過NameServer可以獲取整個Broker集群的路由信息斥扛,從而進(jìn)行消息的投遞和消費。
3.3路由注冊
NameServer通常也是以集群的方式部署丹锹,不過稀颁,NameServer是無狀態(tài)的,即NameServer集群中的各個節(jié)點之間是無差異的楣黍,各個節(jié)點相互不進(jìn)行信息通訊匾灶。那各個節(jié)點中的數(shù)據(jù)是如何進(jìn)行數(shù)據(jù)同步的呢?在Broker節(jié)點啟動時租漂,輪詢NameServer列表阶女,與每個NameServer節(jié)點建立長連接,發(fā)起注冊請求哩治。在NameServer內(nèi)部維護者一個Broker列表秃踩,用來動態(tài)存儲Broker信息
這種NameServer的無狀態(tài)方式,有什么優(yōu)缺點:
優(yōu)點:集群搭建簡單业筏,擴容簡單憔杨。
缺點:對于Broker,必須明確指出所有NameServer地址蒜胖。否則未指出的將不會去注冊消别。也正因為如此抛蚤,NameServer并不能隨便擴容。因為若Broker不重新配置寻狂,新增的NameServer對于Broker來說是不可見的岁经,其不會向這個NameServer進(jìn)行注冊。
Broker節(jié)點為了證明自己是活著的蛇券,為了維護與NameServer間的長連接缀壤,會將最新的信息以心跳包的方式上報給NameServer,每30秒發(fā)送一次心跳怀读。心跳包中包含BrokerId诉位、Broker地址(IP+Port)、Broker名稱菜枷、Broker所屬集群名稱等等苍糠。NameServer在接收到心跳包后,會更新心跳時間戳啤誊,記錄這個Broker的最新存活時間岳瞭。
3.4路由剔除
由于Broker關(guān)機、宕機或網(wǎng)絡(luò)抖動等原因蚊锹,NameServer沒有收到Broker的心跳瞳筏,NameServer可能會將其從Broker列表中剔除
NameServer中有一個定時任務(wù),每隔10秒就會掃描一次Broker表牡昆,查看每一個Broker的最新心跳時間戳距離當(dāng)前時間是否超過120秒姚炕,如果超過,則會判定Broekr失效丢烘,然后將其從Broker列表中剔除柱宦。
對于日常運維工作,例如升級播瞳,OP需要怎么做掸刊?
OP需要將Broker的讀寫權(quán)限禁掉。一旦client向Broker發(fā)送請求赢乓,都會收到NO_PERMISSION相應(yīng)忧侧,然后client會進(jìn)行對其他Broker的重試。
當(dāng)OP觀察到Broker沒有流量后牌芋,再關(guān)閉它蚓炬,實現(xiàn)Broker從NameServer的移除
3.5路由發(fā)現(xiàn)
RocketMQ的路由發(fā)現(xiàn)采用的是Pull模型。當(dāng)Topic路由信息出現(xiàn)變化時躺屁,NameServer不會主動推送給客戶端试吁,而是客戶端定時拉取最新的路由。默認(rèn)每30秒拉取一次最新的路由
1)Push模型:推送模型。其實時性較好熄捍,是一個"發(fā)布-訂閱"模型烛恤,需要維護一個長連接。而長連接的維護是需要資源成本的余耽。該模型適合的場景:
*實時性要求較高
*client數(shù)量不多缚柏,Server數(shù)據(jù)變化較頻繁
2)Pull模型:拉取模型。存在的問題是碟贾,實時性較差
3)Long Polling模型:長輪詢模型币喧。是Push與Pull模型的整合,充分利用了這兩種模型的優(yōu)勢袱耽,屏蔽了他們的劣勢杀餐。
3.6客戶端NameServer選擇策略
客戶端再配置時必須要寫上NameServer集群的地址,那么客戶端道理連接在哪個NameServer節(jié)點呢?客戶端首先會生產(chǎn)一個隨機數(shù)朱巨,然后再與NameServer節(jié)點數(shù)取模史翘,此時得到的就是要連接的節(jié)點索引,然后就會進(jìn)行連接冀续。如果連接失敗琼讽,則會采用round-robin策略,逐個嘗試去連接其他節(jié)點洪唐。
首先采用的是隨機策略
進(jìn)行選擇钻蹬,失敗后采用的是輪詢策略。
Zookeeper Client是如何選擇Zookeeper Server的凭需?
簡單來說就是问欠,經(jīng)過兩次Shufaee,然后選擇第一臺Zookeeper Server粒蜈。
詳細(xì)說就是將配置文件中的zk server地址進(jìn)行第一次shuaee顺献,然后隨機選擇一個。這個選出的一般都是一個hostname,然后獲取到該hostname對應(yīng)的所有ip薪伏,再對這些ip進(jìn)行第二次shufaee,從結(jié)果中獲取第一個server地址進(jìn)行連接
4.Broker
4.1功能介紹
Broker充當(dāng)著消息中轉(zhuǎn)角色粗仓,負(fù)責(zé)存儲消息嫁怀、轉(zhuǎn)發(fā)消息。Broker在RocketMQ系統(tǒng)中負(fù)責(zé)接收并存儲從生產(chǎn)者發(fā)送來的消息借浊,同時為消費者的拉取請求作準(zhǔn)備塘淑。Broker同時也存儲著消息相關(guān)的元數(shù)據(jù),包括消費者組蚂斤、消費進(jìn)度偏移offset存捺、主題、隊列等
Kafuka0.8版本之后,offset是存放在Broker中的捌治,之前版本是存放在Zookeeper中的岗钩。
4.2模塊構(gòu)成
Remoting Module
:整個Broker的實體,負(fù)責(zé)處理來自clients端的請求肖油。而這個Broker實體則由以下模塊構(gòu)成兼吓。
Client Manager
:客戶端管理器。負(fù)責(zé)接收森枪、解析客戶端(Producer/Consumer)請求视搏,管理客戶端。
Store Service
:存儲服務(wù)县袱。提供方便簡單的API接口浑娜,處理消息存儲到物理硬盤和消息查詢功能。
HA Service
:高可用服務(wù)式散,提供Master Broker和Slave Broker之間的數(shù)據(jù)同步功能筋遭。
Index Service
:索引服務(wù)。根據(jù)特定的Message Key杂数,對投遞到Broker的消息進(jìn)行索引服務(wù)宛畦,同時也提供根據(jù)Message Key對消息進(jìn)行快速查詢的功能
4.3集群部署
為了增強Broker性能與吞吐量,Broker一般都是以集群形式出現(xiàn)的揍移。各集群節(jié)點中可能存放著相同Topic的不同Queue次和。
如果某Broker節(jié)點宕機,如何保證數(shù)據(jù)不丟失呢那伐?
其解決方案是踏施,將每個Broekr集群節(jié)點進(jìn)行橫向擴展,即將Broker節(jié)點再建為一個HA集群罕邀,解決單點問題畅形。
Broker節(jié)點集群是一個主從集群,即有Master和Slave兩種角色诉探。Master負(fù)責(zé)處理讀寫操作請求日熬,Slave負(fù)責(zé)對Master中的數(shù)據(jù)進(jìn)行備份。當(dāng)Master掛掉了肾胯,Slaver會自動切換為Master去工作竖席。所以這個Broker集群式主備集群。Master與Slave的對應(yīng)關(guān)系是通過指定相同的BrokerName敬肚、不同的BrokerId來確定的毕荐。BrokerId為0表示Master,非0表示Slave艳馒。每個Broker與NameServer集群中的所有節(jié)點建立長連接憎亚,定時注冊Topic信息到所有NameServer。
5.工作流程
①啟動NameServer,NameServer啟動后開始監(jiān)聽端口第美,等待Broker蝶锋、Producer、Consumer連接
②啟動Broker時斋日,Broker會與所有的NameServer保持長連接牲览,每30秒向NameServer定時發(fā)送心跳包
③發(fā)送消息前,可以先創(chuàng)建Topic ,創(chuàng)建Topic時需要指定該Topic要存儲在哪些Broker上恶守,當(dāng)然第献,在創(chuàng)建Topic時也會將Topic與Broker的關(guān)系寫入到NameServer中。也可以在發(fā)送消息時自動創(chuàng)建Topic兔港。
④Producer發(fā)送消息庸毫,啟動時先跟NameServer集群中的其中一臺建立長連接,并從NameServer中獲取路由信息衫樊,即當(dāng)前發(fā)送Topic的Queue與Broker地址的映射關(guān)系飒赃。然后根據(jù)算法策略從隊選擇一個Queue,與隊列所在的Broker建立長連接從而向Broker發(fā)送消息科侈。
⑤Consumer與Producer類似载佳,跟其中一臺NameServer建立長連接,獲取其所訂閱Topic的路由信息臀栈,然后根據(jù)算法策略從路由信息中獲取到其要消費的Queue蔫慧,然后與Broker建立長連接,消費其中的消息权薯。Consumer會向Broker發(fā)送心跳姑躲,以確保Broker的存活狀態(tài)
6.Topic的創(chuàng)建模式
手動創(chuàng)建Topic時,有兩種模式:
- 集群模式:該模式下創(chuàng)建的Topic在該集群中盟蚣,所有Broker中的Queue數(shù)量是相同的
- Broker模式:該模式下創(chuàng)建的Topic在該集群中黍析,每個Broker中的Queue數(shù)量可以不同
自動創(chuàng)建Topic時,默認(rèn)采用的是Broker模式屎开,會為每個Broker默認(rèn)創(chuàng)建四個Queue
7.讀/寫隊列
從物理上講阐枣,讀/寫隊列是同一個隊列。所以奄抽,不存在讀/寫隊列數(shù)據(jù)同步問題蔼两。讀/寫隊列是邏輯上進(jìn)行區(qū)分的概念 。一般來說如孝,讀/寫隊列數(shù)量是相同的宪哩。
讀/寫隊列數(shù)量不同是有問題的娩贷。
但這樣可以方便縮容
perm用于設(shè)置對當(dāng)前創(chuàng)建Topic的操作權(quán)限:2表示只寫第晰,4表示只讀,6表示讀寫