RocketMQ的Consumer源码分析

本文深入剖析RocketMQ Consumer的启动、Rebalance流程、消息拉取和Offset管理。从配置校验到Consumer实例创建,再到RebalanceService的执行,详细讲解了Consumer如何拉取、处理和管理消息。同时,介绍了不同消费模式下的Offset存储策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RocketMQ的Consumer源码分析


这一节我们分析RocketMQ的Consumer的启动流程以及消息处理过程。下图是RocketMQ启动流程、Rebalance、以及消息拉取处理的较为完整的流程图。
在这里插入图片描述
##Consumer的启动流程

Consumer的启动主要会经过以下步骤:

  1. 校验Consumer一系列的配置,包括消费组、消费者配置等信息
    • 校验消费组是否非空、是否超长、是否含有非法字符、是否系统占用等
    • 校验一系列配置信息是否设置,如消费模式、消费位置、消息监听器等
    • 校验消费者线程大小、消费者拉取消息的大小、批次大小等
  2. 复制订阅信息到RebalanceImpl,copySubscription()会把当前Topic的订阅信息放到RebalanceImpl的map中
  3. 如果是集群消费模式,使用PID设置实例名称
  4. 创建MQClientInstance,会优先从缓存中获取,如果缓存中有则直接返回,这也意味着相同的clientId会共享MQClientInstance
  5. 为RebalanceImpl设置所需要的属性,如消费组、消费模式、Queue分配策略等
  6. 初始化一个PullAPIWrapper,这个PullAPIWrapper是会为后面从Broker拉取消息服务
  7. 执行offsetStore.load(),广播模式下会选择从本地加载消费进度,集群模式默认什么也不做
  8. 根据顺序/并发消费方式初始化对应的消息消费服务
  9. 启动消息消费服务,这里会开启一个延时任务定期执行
    • 对于并发消费方式,会定期清理过期消息,默认每15分钟执行一次
    • 对于顺序消费方式且为集群消费模式时,会定期将消费的Queue锁定,默认每20秒执行一次
  10. 向MQClientInstance注册Consumer,相同的consumerGroup共享DefaultMQPushConsumer
  11. 启动MQClientInstance,这一步在初始化过程是Consumer启动的关键
    • 如果没有指定NameServer地址,则会尝试从配置中心拉取,我们通常会在启动Producer时指定,没有指定的场景通常用在多集群的业务中,方便统一进行管理
    • 启动MQClientAPIImpl,这里会完成NettyClient的初始化,为网络通信做准备
    • 开启一系列的定时任务
      • 如果没有指定NameServer地址,则定期从配置中心拉取
      • 定期更新Topic的路由信息,这里会随机选择一个NameServer进行通信,获取topic对应的路由信息并更新到本地的内存中
      • 定期清理下线的Broker,并且给所有的Broker发送心跳,默认每30秒执行一次
      • 定期持久化消费进度,默认每5秒执行一次
      • 定期调整消费者线程大小
    • 启动PullMessageService,开始处理PullRequest,PullMessageService是一个循环执行的线程
      • 从pullRequestQueue队列中获取一个PullRequest,如果没有获取到则会阻塞直到从队列中获取到数据为止
      • 根据消费组获取到对应的MQConsumerInner实例,PullRequest中会有对应的consumerGroup信息
      • 最终调用DefaultMQPushConsumerImpl.pullMessage()方法,完成消息的拉取,具体过程在下面详细分析
    • 启动RebalanceService,开始执行rebalance,RebalanceService是一个循环执行的线程,限时等待被唤醒
      • 随后调用mqClientFactory.doRebalance(),在MQClientInstance中,会遍历所有的消费组,执行Rebalance操作
      • 最终调用到RebalanceImpl.doRebalance()方法,具体过程在下面详细分析
    • 初始化内置的Producer
  12. 设置Consumer状态为RUNNING,刚启动时Consumer状态是START_FAILED
  13. 从NameServer获取订阅的Topic路由信息并更新本地缓存
  14. 从路由信息中随机找一个Broker,检查Broker是否支持消费者端对该Topic的订阅方式
  15. 向所有的Broker发送心跳,因为需要和所有的Broker通信
  16. 唤醒RebalanceService服务,立即进行一次Rebalance

Consumer的Rebalance流程

Consumer的rebalance流程是通过RebalanceService线程来执行的,当RebalanceService线程被唤醒后,执行以下逻辑

  1. Consumer的rebalance会调用RebalanceImpl.doRebalance()方法,该方法会对订阅的所有topic依此进行rebalanceByTopic()

    public void doRebalance(final boolean isOrder) {
         
        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) {
         
                    if (!topic.startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX)) {
         
                        log.warn("rebalanceByTopic Exception", e);
                    }
                }
            }
        }
    
        this.truncateMessageQueueNotMyTopic();
    }
    
  2. 如果当前topic是广播消费模式,则消费者可以消费所有有效的Message Queue

  3. 如果当前topic是集群消费模式,则按照分配策略分配queue

    • 获取该Topic对应的所有mqSet

    • 根据consume group获取订阅了该topic的消费者信息(随机选择一个Broker发送网络请求获取)

    • 按照queue的分配策略(默认为平均分配策略,AllocateMessageQueueAveragely)取得queue的分配结果,目前支持以下分配策略

      AllocateMessageQueueAveragely:平均分配,将该topic下所有Queue按照brokerId和queueId从小到大排序,按照Consumer数量平均分为若干份,每个Consumer分配一份。
      AllocateMessageQueueAveragelyByCircle:环形平均分配,和平均分配策略类似,只是每个Consumer分配到的queueId不是连续的。
      AllocateMessageQueueByConfig:通过配置分配,用户启动时可以指定消费哪些Queue
      AllocateMessageQueueConsistentHash:一致性哈希,使用一致性hash算法来分配Queue,用户需自定义虚拟节点的数量。
      AllocateMessageQueueByMachineRoom:按照机房分配,将queue按照Broker划分为几个machine room,不同的Consumer只消费某几个特定Broker上的消息。
      AllocateMachineRoomNearby:机房就近分配,与按照机房分配类似,只是在AllocateMessageQueueByMachineRoom的基础上,会优先为Consumer分配在同一个machine room的Broker上的queue。
      
  4. 根据分配的mqSet更新

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值