RocketMQ源码阅读(十)Consumer-消息队列负载均衡

目录

RebalanceService

RebalanceImpl

rebalanceByTopic

AllocateMessageQueueStrategy

updateProcessQueueTableInRebalance


入口org.apache.rocketmq.client.impl.factory.MQClientInstance#start

RocketMQ的消息消费流程分为三部分,一消息队列负载均衡,二消息的拉取,三消息的消费

RebalanceService

负载均衡定时任务的实现类

 org.apache.rocketmq.client.impl.factory.MQClientInstance#doRebalance

 org.apache.rocketmq.client.impl.consumer.DefaultMQPushConsumerImpl#doRebalance

RebalanceImpl

org.apache.rocketmq.client.impl.consumer.RebalanceImpl#doRebalance

rebalanceByTopic

广播模式所有队列都需订阅, 不用负载均衡,下边只关注集群模式

1、获取所有消息队列和消费者实例

2、使用负载均衡算法进行分配

3、根据分配后最新的队列信息,进行消息拉取或停止原队列消费 

    private void rebalanceByTopic(final String topic, final boolean isOrder) {
        switch (messageModel) {
            case BROADCASTING: {
              。。。。
            case CLUSTERING: {
                // 从缓存表获取该Topic所有的消息队列
                Set<MessageQueue> mqSet = this.topicSubscribeInfoTable.get(topic);

                // 从Broker获取该消费者组所有消费者列表
                List<String> cidAll = this.mQClientFactory.findConsumerIdList(topic, consumerGroup);

                if (mqSet != null && cidAll != null) {
                    List<MessageQueue> mqAll = new ArrayList<MessageQueue>();
                    mqAll.addAll(mqSet);

                    Collections.sort(mqAll);
                    Collections.sort(cidAll);

                    // 负载均衡策略处理
                    AllocateMessageQueueStrategy strategy = this.allocateMessageQueueStrategy;

                    List<MessageQueue> allocateResult = null;
                    try {
                        allocateResult = strategy.allocate(
                            this.consumerGroup,
                            this.mQClientFactory.getClientId(),
                            mqAll,
                            cidAll);
                    } catch (Throwable e) {
                        log.error("AllocateMessageQueueStrategy.allocate Exception. allocateMessageQueueStrategyName={}", strategy.getName(),
                            e);
                        return;
                    }

                    Set<MessageQueue> allocateResultSet = new HashSet<MessageQueue>();
                    if (allocateResult != null) {
                        allocateResultSet.addAll(allocateResult);
                    }

                    // 根据最新的队列信息,更新本地
                    // 如果有队列被移除,停止消费原队列
                    // 如果有队列新增,新增拉取消息的任务
                    boolean changed = this.updateProcessQueueTableInRebalance(topic, allocateResultSet, isOrder);
                    if (changed) {
                        log.info(
                            "rebalanced result changed. allocateMessageQueueStrategyName={}, group={}, topic={}, clientId={}, mqAllSize={}, cidAllSize={}, rebalanceResultSize={}, rebalanceResultSet={}",
                            strategy.getName(), consumerGroup, topic, this.mQClientFactory.getClientId(), mqSet.size(), cidAll.size(),
                            allocateResultSet.size(), allocateResultSet);
                        this.messageQueueChanged(topic, mqSet, allocateResultSet);
                    }
                }
                break;
            }
            default:
                break;
        }
    }

AllocateMessageQueueStrategy

分配队列的策略接口,实现类有如下,假设有8个消费队列,3个消费者ABC

AllocateMessageQueueAveragely  默认使用的,分配后A123, B456, C67

AllocateMessageQueueAveragelyByCircle  分配后A147     B258    C36

AllocateMessageQueueConsistentHash   环形一致性hash算法,下节

AllocateMessageQueueByConfig   自定义配置,为每个消费者自定义要订阅的队列

AllocateMessageQueueByMachineRoom   也是自定义配置,每个消费者只负载自定义配置的机房中Broker的队列信息,BrokerName也需要规范命名

AllocateMessageQueueAveragely#allocate  代码如下

updateProcessQueueTableInRebalance

如果有删除的队列,停止消费消息,移除消息队列

如果有新增的队列,新增消息拉取任务

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值