RocketMQ消费者消息获取

RocketMQ 消费者没有服务端主动推送 ,本质是 PULL 拉模型;所谓 PushConsumer 只是 SDK 封装的伪推送,底层依然是循环向 Broker 发拉取请求。

两种模式

  1. PullConsumer:手动调用 pull (),自己控制什么时候去拉消息。
  2. DefaultMQPushConsumer(常用):底层自动 PULL 长轮询

流程:

  1. 消费者发送 PullRequest 请求 Broker:我要拉取某一个 MessageQueue 的消息。
  2. Broker 收到请求:
    • 如果有消息:立刻把消息返回给消费者。
    • 如果没有消息 :Broker不马上返回 response,把这个 pull 请求挂起,保存到等待队列。
  3. Broker 当收到新消息写入该队列时,唤醒挂起的 pull 请求,立刻返回消息给客户端。
  4. 如果一直没有消息,等待超时(默认 30s),返回空结果;消费者收到空,马上发起下一次 pull 请求。

长轮询机制

RocketMQ 底层都是通过 Netty 框架进行的通信(异步非阻塞 IO)。消费者向 Broker 发送 pull 请求后,业务线程不会阻塞,等 Broker 返回后通过回调函数处理结果,有消息则消费消息,无消息则重新发起 pull 请求。Broker 收到请求后也不会阻塞等待,先判断有无消息,若是有消息则立即返回,没有消息则将请求加入等待队列。默认等待 30s,期间有消息则唤醒请求返回消费者,没有消息则返回空结果。

这里有几个关键点值得展开:

  • 消费者侧不阻塞:发送 pull 请求后,消费者线程可以继续做其他事情,等 Broker 响应回来再通过回调处理,因此单个消费者可以同时挂起多个 pull 请求,提升吞吐。
  • Broker 侧也不阻塞:Broker 收到 pull 请求后,如果暂时没有消息,不会让线程干等,而是把请求挂到等待队列里,释放线程资源去处理其他请求。
  • 等待队列的作用:挂起的请求会记录消费者要拉的 MessageQueue 和 offset,等新消息到达时,Broker 能精准找到对应的挂起请求并唤醒它。
  • 超时兜底:如果 30s 内一直没有新消息,Broker 会主动返回空结果,避免请求无限期挂起;消费者收到空结果后立即发起下一次 pull,形成持续的轮询循环。
  • 长轮询的价值:相比普通轮询(拉不到就立刻返回),长轮询让 Broker 帮忙"等一会儿",既减少了空轮询的次数,又能保证消息到达后尽快被消费,兼顾实时性和性能。

broker如何判断有无消息

Broker 处理 pull 请求时:

读取这个 queue 对应的 ConsumeQueue ,对比消费者提交的offset

  • 如果 offset < ConsumeQueue最大offset → 有新消息,读取返回;
  • 如果 offset 已经追到末尾,没有新消息 → 将 pull 请求挂起,进入长轮询等待。

⚠️注意:判断有无消息看 ConsumeQueue 索引 ,不直接看 CommitLog。ReputMessageService 异步把消息构建进 ConsumeQueue 之后,pull 请求才看得到这条消息。

刚写入 CommitLog 但还没构建 ConsumeQueue 的消息,长轮询也看不到。

相关推荐
云和数据.ChenGuang21 分钟前
git revert回退问题
java·服务器·人工智能·git·fastapi·强化学习
lhldsg40 分钟前
AI智能商城实战指南:从架构设计到落地开发经验分享
java·人工智能·经验分享·小程序
lhldsg1 小时前
树洞交友系统开发实战:从匿名社交需求到技术落地
java·小程序·uni-app·交友
数智启示录1 小时前
实时数据湖 Flink CDC + Kafka +Doris 【企业级实战】之Kafka 事件缓冲层 【附核心源码】 04
java·大数据·flink·kafka·数据库开发
AI人工智能+电脑小能手1 小时前
大白话说Java设计模式-41-备忘录模式(源码剖析篇)
java·设计模式·备忘录模式·源码分析·serializable·undo log·spring statemachine
lv__pf1 小时前
Sentinel【TL微服务10、11】
java·微服务·sentinel
Escalating_xu1 小时前
【C++ string 上篇】从字符串基础到容量管理、迭代器与经典算法题
java·c++·算法
曹牧2 小时前
Java:Java 数组转 List
java·开发语言·windows
下辈子不要当码农2 小时前
Day7-Linux软件编程(进程与线程(3))
java·开发语言