RocketMQ - 消费者消费方式
RocketMQ的消费方式包含Pull和Push两种
Pull方式:用户主动Pull消息,自主管理位点,可以灵活地掌控消费进度和消费速度,适合流计算、消费特别耗时等特殊的消费场景。缺点也显而易见,需要从代码层面精准地控制消费,对开发人员有一定要求。 在 RocketMQ 中org.apache.rocketmq.client.consumer.DefaultMQPullConsumer 是默认的Pull消费者实现类。
Push 方式:代码接入非常简单,适合大部分业务场景。缺点是灵活度差,在了解其消费原理后,排查消费问题方可简单快捷。在RocketMQ 中org.apache.rocketmq.client.consumer.DefaultMQPushConsumer 是默认的Push消费者实现类
| 消费方式/对比项 | Pull | Push | 备注 |
|---|---|---|---|
| 是否需要主动拉取 | 理解分区后,需要主动拉取各个分区消息 | 自动 | Pull 消息灵活;Push 使用更简单 |
| 位点管理 | 用户自行管理或者主动提交给 Broker 管理 | Broker 管理 | Pull自主管理位点,消费灵活; Push 位点交由 Broker 管理 |
| Topic 路由变更是否影响消费 | 否 | 否 | Pull模式需要编码实现路由感知 Push 模式自动执行 Rebalance,以适应路由变更 |
Pull消费流程

第一步: fetchSubscribeMessageQueues(StringTopic)。拉取全部可以消费的Queue。如果某一个Broker下线,这里也可以实时感知到。
第二步: 遍历全部Queue,拉取每个Queue可以消费的消息。
第三步: 如果拉取到消息,则执行用户编写的消费代码。
第四步: 保存消费进度。消费进度可以执行updateConsumeOffset()方法,将消费位点上报给Broker,也可以自行保存消费位点。比如流计算平台Flink使用Pull方式拉取消息消费,通过Checkpoint管理消费进度
Push消费流程

第一步: 初始化Push消费者实例。业务代码初始化DefaultMQPushConsumer实例,启动Pull服务PullMessageService。该服务是一个线程服务,不断执行run()方法拉取已经订阅Topic的全部队列的消息,将消息保存在本地的缓存队列中。
第二步: 消费消息。由消费服务ConsumeMessageConcurrentlyService或者ConsumeMessageOrderlyService将本地缓存队列中的消息不断放入消费线程池,异步回调业务消费代码,此时业务代码可以消费消息。
第三步: 保存消费进度。业务代码消费后,将消费结果返回给消费服务,再由消费服务将消费进度保存在本地,由消费进度管理服务定时和不定时地持久化到本地(LocalFileOffsetStore支持)或者远程Broker(RemoteBrokerOffsetStore支持)中。对于消费失败的消息,RocketMQ客户端处理后发回给Broker,并告知消费失败
Push消费者如何拉取消息消费

第一步:PullMessageService 不断拉取消息。如下源代码是PullMessageService.run()方法,pullRequestQueue 中保存着待拉取的 Topic 和 Queue 信息,程序不断从pullRequestQueue中获取PullRequest并执行拉取消息方法。
第二步:消费者拉取消息并消费
(1)基本校验。校验ProcessQueue是否dropped;校验消费者服务状态是否正常;校验消费者是否被挂起。
(2)拉取条数、字节数限制检查。如果本地缓存消息数量大于配置的最大拉取条数(默认为1000,可以调整),则延迟一段时间再拉取;如果本地缓存消息字节数大于配置的最大缓存字节数,则延迟一段时间再拉取。这两种校验方式都相当于本地流控
(3)并发消费和顺序消费校验,在并发消费时,processQueue.getMaxSpan()方法是用于计算本地缓存队列中第一个消息和最后一个消息的offset差值

本地缓存队列的Span如果大于配置的最大差值(默认为2000,可以调整),则认为本地消费过慢,需要执行本地流控
顺序消费时,如果当前拉取的队列在 Broker 端没有被锁定,说明已经有拉取正在执行,当前拉取请求晚点执行;如果不是第一次拉取,需要先计算最新的拉取位点并修正本地最新的待拉取位点信息,再执行拉取
(1)订阅关系校验。如果待拉取的Topic在本地缓存中订阅关系为空,则本地拉取不执行,待下一个正常心跳或者Rebalance后订阅关系恢复正常,方可正常拉取。
(2)封装拉取请求和拉取后的回调对象 PullCallback。这里主要将消息拉取请求和拉取结果处理封装成 PullCallback,并通过调用PullAPIWrapper.pullKernelImpl()方法将拉取请求发出去
ConsumeMessageService 是一个通用消费服务接口
public interface ConsumeMessageService {
/**
* 启动服务时使用
*/
void start();
/**
* 关闭服务时使用
* @param awaitTerminateMillis
*/
void shutdown(long awaitTerminateMillis);
/**
* 更新消费线程池的核心线程数。
* @param corePoolSize
*/
void updateCorePoolSize(int corePoolSize);
/**
* 增加一个消费线程池的核心线程数。
*/
void incCorePoolSize();
/**
* 减少一个消费线程池的核心线程数
*/
void decCorePoolSize();
/**
* 获取消费线程池的核心线程数
* @return
*/
int getCorePoolSize();
/**
* 如果一个消息已经被消费过了,但是还想再消费一次,就需要实现这个方法
* @param msg
* @param brokerName
* @return
*/
ConsumeMessageDirectlyResult consumeMessageDirectly(final MessageExt msg, final String brokerName);
/**
* 将消息封装成线程池任务,提交给消费服务,消费服务再将消息传递给业务消费进行处理
* @param msgs
* @param processQueue
* @param messageQueue
* @param dispathToConsume
*/
void submitConsumeRequest(
final List<MessageExt> msgs,
final ProcessQueue processQueue,
final MessageQueue messageQueue,
final boolean dispathToConsume);
}
消费消息主要分为消费前预处理、消费回调、消费结果统计、消费结果处理4个步骤
第一步:消费执行前进行预处理。执行消费前的hook和重试消息预处理。消费前的hook可以理解为消费前的消息预处理(比如消息格式校验)。如果拉取的消息来自重试队列,则将Topic名重置为原来的Topic名,而不用重试Topic名。
第二步:消费回调。首先设置消息开始消费时间为当前时间,再将消息列表转为不可修改的List,然后通过listener.consumeMessage(Collections.unmodifiableList(msgs),context)方法将消息传递给用户编写的业务消费代码进行处理。
第三步:消费结果统计和执行消费后的hook。客户端原生支持基本消费指标统计,比如消费耗时;消费后的hook和消费前的hook要一一对应,用户可以用消费后的hook统计与自身业务相关的指标。
第四步:消费结果处理。包含消费指标统计、消费重试处理和消费位点处理。消费指标主要是对消费成功和失败的TPS的统计;消费重试处理主要将消费重试次数加1;消费位点处理主要根据消费结果更新消费位点记录
顺序消息的 ConsumeRequest 中并没有保存需要消费的消息,在顺序消费时通过调用ProcessQueue.takeMessags()方法获取需要消费的消息,而且消费也是同步进行的
msgTreeMap:是一个TreeMap<Long,MessageExt>类型,key是消息物理位点值,value是消息对象,该容器是ProcessQueue用来缓存本地顺序消息的,保存的数据是按照key(就是物理位点值)顺序排列的。
consumingMsgOrderlyTreeMap:是一个TreeMap<Long,MessageExt>类型,key是消息物理位点值,Value是消息对象,保存当前正在处理的顺序消息集合,是msgTreeMap的一个子集。保存的数据是按照key(就是物理位点值)顺序排列的。
batchSize:一次从本地缓存中获取多少条消息回调给用户消费
RocketMQ - 消费者消费方式的更多相关文章
- RocketMQ的push消费方式实现的太聪明了
大家好,我是三友,我又来了~~ 最近仍然畅游在RocketMQ的源码中,这几天刚好翻到了消费者的源码,发现RocketMQ的对于push消费方式的实现简直太聪明了,所以趁着我脑子里还有点印象的时候,赶 ...
- 【转】RocketMQ事务消费和顺序消费详解
RocketMQ事务消费和顺序消费详解 转载说明:该文章纯转载,若有侵权或给原作者造成不便望告知,仅供学习参考. 一.RocketMq有3中消息类型 1.普通消费 2. 顺序消费 3.事务消费 顺序消 ...
- RocketMQ(7)---RocketMQ顺序消费
RocketMQ顺序消费 如果要保证顺序消费,那么他的核心点就是:生产者有序存储.消费者有序消费. 一.概念 1.什么是无序消息 无序消息 无序消息也指普通的消息,Producer 只管发送消息,Co ...
- RocketMq 集群方式搭建 步骤教学包教包会
mq集群方式搭建 有段时间没写这些技术文章了, 今天抽空写一点,不然自己都快忘记了 这篇文章记录了rocketmq 集群方式搭建的过程, 也是自己半天的成果记录吧! 感兴趣的朋友点个赞在走呗! 好了, ...
- 深入研究RocketMQ消费者是如何获取消息的
前言 小伙伴们,国庆都过的开心吗?国庆后的第一个工作日是不是很多小伙伴还沉浸在假期的心情中,没有工作状态呢? 那王子今天和大家聊一聊RocketMQ的消费者是如何获取消息的,通过学习知识来找回状态吧. ...
- RocketMQ消费者示例程序
转载请注明出处:http://www.cnblogs.com/xiaodf/ 本博客实现了一个简单的RocketMQ消费者的示例,MQ里存储的是经过Avro序列化的消息数据,程序读取数据并反序列化后, ...
- Kafka技术内幕 读书笔记之(三) 消费者:高级API和低级API——消费者消费消息和提交分区偏移量
消费者拉取钱程拉取每个分区的数据,会将分区的消息集包装成一个数据块( FetchedDataChunk )放入分区信息的队列中 . 而每个队列都对应一个消息流( KafkaStream ),消费者客户 ...
- 关于RocketMQ消息消费与重平衡的一些问题探讨
其实最好的学习方式就是互相交流,最近也有跟网友讨论了一些关于 RocketMQ 消息拉取与重平衡的问题,我姑且在这里写下我的一些总结. ## 关于 push 模式下的消息循环拉取问题 之前发表了一篇关 ...
- 一次 RocketMQ 顺序消费延迟的问题定位
一次 RocketMQ 顺序消费延迟的问题定位 问题背景与现象 昨晚收到了应用报警,发现线上某个业务消费消息延迟了 54s 多(从消息发送到MQ 到被消费的间隔): 2021-06-30T23:12: ...
- Spring Cloud Alibaba基础教程:支持的几种服务消费方式(RestTemplate、WebClient、Feign)
通过<Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现>一文的学习,我们已经学会如何使用Nacos来实现服务的注册与发现,同时也介绍如何通过LoadBal ...
随机推荐
- Qwt开发笔记(二):Qwt基础框架介绍、折线图介绍、折线图Demo以及代码详解
前言 QWT开发笔记系列整理集合,这是目前使用最为广泛的Qt图表类(Qt的QWidget代码方向只有QtCharts,Qwt,QCustomPlot),使用多年,系统性的整理,本系列旨在系统解说并 ...
- 全都会!预测蛋白质标注!创建讲义!解释数学公式!最懂科学的智能NLP模型Galactica尝鲜 ⛵
作者:韩信子@ShowMeAI 机器学习实战系列:https://www.showmeai.tech/tutorials/41 深度学习实战系列:https://www.showmeai.tech/t ...
- python语法之注释
引言 注释的最大作用是提高程序的可读性,在开发过程中非常有必要加上注释.Python 支持两种类型的注释,分别是单行注释和多行注释. 1 单行注释 Python 使用井号#作为单行注释的符号,语法格式 ...
- Jenkins&&gitlab2
Jenkins slave 添加jenkins slave节点: jenkins slave节点创建工作目录与基本环境配置,如果jenkins slave节点需要clone代码和执行java 代码编 ...
- [机器学习] sklearn支持向量机
支持向量机SVM(Support Vector Machine)是一种用来进行模式识别.分类.回归的机器学习模型. SVM原理描述 模型表示 以一个客户好坏分类为案例,客户信息如下所示: 客户信息数轴 ...
- .Net 7 被Microsoft的开源免费PowerToys工具独立附带
楔子 什么是PowerToys? Microsoft PowerToys 是一组实用工具,可帮助高级用户调整和简化其 Windows 体验,从而提高工作效率. 简而言之,就是给最新的windows11 ...
- BBS项目 未完待续
项目开发基本流程 1.需求分析 2.架构设计 3.分组开发 4.提交测试 5.交付上线 创建项目配置 环境配置 TEMPLATES = [ { 'BACKEND': 'django.template. ...
- [C++]union联合体总结
特点一:成员公用内存,且按所占内存最大的数据成员分配内存 //举例1 union A{ char a;//1个字节 int b;//4个字节 char c;//1个字节 } cout<<s ...
- ac自动姬
字符串 ac自动姬 前言 省选临近,不能再颓了! 说着开始研究起moonlight串流.真香 本期博客之所以在csdn上发了一份,因为没有图床!如果有图床我一定会自力更生的! 好像和字符串没有毛关系 ...
- C Primer Plus(4.8)編程練習
/*C Primer Plus (4.7) 5*/ 1 include<stdio.h> 2 #define BOOK "War and Peace" 3 int ma ...