在RocketMQ启动的时候会启动负载均衡线程,过程如下:
//DefaultMQPullConsumerImpl.start()
mQClientFactory.start();
//上面点进去 ->MQClientInstance.start(),rebalanceService继承了ServiceThread,
//ServiceThread实现了Runnable接口
this.rebalanceService.start();
//继续下一层,MQClientInstance.doRebalance()找到下面
impl.doRebalance();
//..在一层层点进去,最后找到RebalanceImpl.rebalanceByTopic方法,找到
AllocateMessageQueueStrategy strategy = this.allocateMessageQueueStrategy;
AllocateMessageQueueStrategy就是实现消费者消息队列负载均衡算法的接口。
该接口在rocketMq-4.3.0版本中有六种实现方法:
- AllocateMessageQueueAveragely:平均算法
- AllocateMessageQueueAveragelyByCircle:环形平均算法
- AllocateMessageQueueByConfig:根据配置负载均衡算法
- AllocateMessageQueueByMachineRoom:根据机房负载均衡算法
- AllocateMessageQueueConsistentHash:一致性哈希负载均衡算法
- AllocateMachineRoomNearby:靠近机房策略
在客户端没有指定的情况下,RocketMQ默认使用AllocateMessageQueueAveragely平均算法。
一、 AllocateMessageQueueAveragely平均负载均衡算法
平均算法顾名思义就是取平均值,该方法四个参数,consumerGroup(消费者组名称)、
currentCID(当前消费者的id)、mqAll(当前topic下面所有的消息队列)、cidAll(当前消费者组下面所有的消费者id)。算法思想就是把算出平均值然后将连续的队列分配给每个消费者。假设队列大小是8(编号0-7),消费者数量3(编号0-2),分配结果就是:
消费者0:队列0,1,2;
消费者1:队列3,4,5;
消费者2:队列6,7。
下面具体来看代码:
@Override
public List<MessageQueue> allocate(String consumerGroup, String currentCID, List<MessageQueue> mqAll,
List<String> cidAll) {
if (currentCID == null || currentCID.length() < 1) {
throw new IllegalArgumentException("currentCID is empty");
}
if (mqAll == null || mqAll.isEmpty()) {
throw new IllegalArgumentException("mqAll is null or mqAll empty");
}
if (cidAll == null || cidAll.isEmpty()) {
throw new IllegalArgumentException("cidAll is null or cidAll empty");
}
List<MessageQueue> result = new ArrayList<MessageQueue>();
if (!cidAll.contains(currentCID)) {
log.info("[BUG] ConsumerGroup: {} The consumerId: {} not in cidAll: {}",
consumerGroup,
currentCID,
cidAll);
return result;
}
// cidAll.size() = 3; mqAll.size()=8;mod=2;
// index=0;averageSize=3;startIndex=0;range=3,result={0,1,2}
// index = 1;averageSize=3;startIndex=3;range = 3;result={3,4,5}
// index = 2;averageSize=2;startIndex=6;range = 2;result={6,7}
int index = cidAll.indexOf(currentCID);
//取模a除以b的余数
int mod = mqAll.size() % cidAll.size();
int averageSize =
mqAll.size() <= cidAll.size() ? 1 : (mod > 0 && index < mod ? mqAll.size() / cidAll.size()
+ 1 : mqAll.size() / cidAll.size());
int startIndex = (mod > <