从入门到入土(八)RocketMQ的Consumer是如何做的负载均衡的
一、问题描述
面试官:RocketMQ的Consumer是如何做的负载均衡?比如:5个Consumer进程同时消费一个Topic,这个Topic只有4个queue会出现啥情况?反之Consumer数量小于queue的数据是啥情况?
应聘者:一脸懵逼。
二、源码剖析
1、RebalancePushImpl
public class RebalancePushImpl extends RebalanceImpl {
public RebalancePushImpl(String consumerGroup, MessageModel messageModel,
AllocateMessageQueueStrategy allocateMessageQueueStrategy,
MQClientInstance mQClientFactory, DefaultMQPushConsumerImpl defaultMQPushConsumerImpl) {
// 可以看到很简单,调用了父类RebalanceImpl的构造器
super(consumerGroup, messageModel, allocateMessageQueueStrategy, mQClientFactory);
this.defaultMQPushConsumerImpl = defaultMQPushConsumerImpl;
}
2、RebalanceImpl
public abstract class RebalanceImpl {
// 很简单,就是初始化一些东西,关键在于下面的doRebalance
public RebalanceImpl(String consumerGroup, MessageModel messageModel,
AllocateMessageQueueStrategy allocateMessageQueueStrategy,
MQClientInstance mQClientFactory) {
this.consumerGroup = consumerGroup;
this.messageModel = messageModel;
this.allocateMessageQueueStrategy = allocateMessageQueueStrategy;
this.mQClientFactory = mQClientFactory;
}
/**
* 分配消息队列,命名抄袭spring,doXXX开始真正的业务逻辑
*
* @param isOrder:是否是顺序消息 true:是;false:不是
*/
public void doRebalance(final boolean isOrder) {
// 分配每个topic的消息队列
Map<String, SubscriptionData> subTable = this.getSubscriptionInner();
if (subTable != null) {
for (final Map.Entry<String, SubscriptionData> entry : subTable.entrySet()) {
final String topic = entry.getKey();
try {
// 这个是关键了
this.rebalanceByTopic(topic, isOrder);
} catch (Throwable e) {