Producer的負載均衡
Producer端在發送消息的時候,會先根據Topic找到指定的TopicPublishInfo,在獲取了TopicPublishInfo路由信息後,RocketMQ的客户端在默認⽅式下selectOneMessageQueue()⽅法會從TopicPublishInfo中的messageQueueList中選擇⼀個隊列(MessageQueue)進⾏發送消息。
具體的容錯策略均在MQFaultStrategy這個類中定義。
這⾥有⼀個sendLatencyFaultEnable開關變量,如果開啓,在隨機遞增取模的基礎上,再過濾掉not available的Broker代理。所謂的"latencyFaultTolerance", 是指對之前失敗的,按⼀定的時間做退避。例如,如果上次請求的latency超過550Lms,就退避3000Lms;超過1000L,就退避60000L;
如果關閉,採⽤隨機遞增取模的⽅式選擇⼀個隊列(MessageQueue)來發送消息,latencyFaultTolerance機 制是實現消息發送⾼可⽤的核⼼關鍵所在。
在Rocketmq裏面,負載均衡分成了兩個部分,一個是生產者的負載均衡,另外一個是消費者的負載均衡。
RocketMQ中的負載均衡都在Client端完成,具體來説的話,主要可以分為Producer端發送消息時候的負載均衡和Consumer端訂閲消息的負載均衡。
生產者要去發送消息,這個消息會往某個topic上去發,這個topic會分佈在兩個broker上面,然後每個broker上面有4個隊列。也就是消息會發到某個broker上面的某個隊列上面,這個時候就和生產者的負載均衡有關係了。
其實看源碼也就是一個一個隊列按照順序發,其實生產端的負載均衡就是一個一個下來。
在發送第一次的時候是brokera上面的最後一個隊列,然後是brokerb上面的0號隊列,再是1 2 3號。再按照順序是a的0號,1 2 3號。在會話中每一條消息能夠按照輪詢的方式找到隊列然後順序發送過去。
Consumer的負載均衡
在RocketMQ中,Consumer端的兩種消費模式(Push/Pull)都是基於拉模式來獲取消息的,⽽在Push模式只是對pull模式的⼀種封裝,其本質實現為消息拉取線程在從服務器拉取到⼀批消息後,然後提交到消息消費線程池後,⼜“⻢不停蹄”的繼續向服務器再次嘗試拉取消息。如果未拉取到消息,則延遲⼀下⼜繼續拉取。
在兩種基於拉模式的消費⽅式(Push/Pull)中,均需要Consumer端在知道從Broker端的哪⼀個消息隊列—隊列中去獲取消息。因此,有必要在Consumer端來做負載均衡,即Broker端中多個MessageQueue分配給同⼀個ConsumerGroup中的哪些Consumer消費。
Consumer的負責均衡可以通過consumer的api進⾏設置:
consumer.setAllocateMessageQueueStrategy(new
AllocateMessageQueueAveragelyByCircle());
AllocateMessageQueueStrategy接⼝的實現類表達了不同的負載均衡策略:
a.AllocateMachineRoomNearby :基於機房近側優先級的代理分配策略。可以指定實
際的分配策略。如果任何使⽤者在機房中活動,則部署在同⼀台機器中的代理的消
息隊列應僅分配給這些使⽤者。否則,這些消息隊列可以與所有消費者共享,因為
沒有活着的消費者可以壟斷它們
b.AllocateMessageQueueAveragely:平均哈希隊列算法(默認使用)
c.AllocateMessageQueueAveragelyByCircle:循環平均哈希隊列算法
d.AllocateMessageQueueByConfig:不分配,通過指定MessageQueue列表來消費
e.AllocateMessageQueueByMachineRoom:機房哈希隊列算法,如⽀付寶邏輯機房
f.AllocateMessageQueueConsistentHash:⼀致哈希隊列算法,帶有虛擬節點的⼀致性
哈希環。
注意,在MessageQueue和Consumer之間⼀旦發⽣對應關係的改變,就會觸發 rebalance,進⾏重新分配。
兩個消費者屬於同一個消費組,按照邏輯是一個隊列只能被一個消費組裏面的一個消費者消費。現在其中一個隊列被消費者消費。
比如第一個消費者消費到的隊列是比較多的,消費了6個隊列,但是第二個消費者只消費了兩個隊列,所以負載並不均衡。
所以這個時候如何去分配