RocketMQ 用法详解,你学会了吗?

SpringBoot RocketMQ消息监听器(RocketMQMessageListener)后置注册 SpringBoot RocketMQ可以从源码中查看到实现了**SmartInitializingSingleton**接口,在所有Bean注册完成之后就会开始注册,注册使用的是main线程,就会导致如果消息队列积压大量消息时注册占用main线程时间过长,导致SpringBoot不能完全完成初始化(主要影响web无法对外提供接口访问) 阅读详情

大家好,我是指北君。

消息中间件是我们工作中使用最频繁的一类中间件,它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能,成为异步RPC的主要手段之一。当今市面上有很多主流的消息中间件,如老牌的ActiveMQ、RabbitMQ,炙手可热的Kafka,阿里巴巴自主开发RocketMQ等。今天,指北君就来详细讲讲RocketMQ生产者和消费者在使用时的一些注意事项。

一. 生产者

1.1 发送消息注意事项

1)消息大小

建议消息大小不要超过512K。

2)异步发送

默认的发送为同步发送,send方法会一直阻塞,等待broker端的响应。如果你关注性能问题,可以通过send(msg, callback)来发起异步调用。

3)生产者组

正常情况下生产者组是没有作用的,但是在发送事务消息时,如果producer中途意外宕机,broker会主动回调producer group 内的任意一台机器来确认事务的状态。(目前开源版本还不支持事务消息)。

4)线程安全问题

生产者实例是线程安全的,在应用中只需要实例化一次即可。

5)性能问题

如果你希望在一个jvm进程内使用多个producer实例来提高发送能,我们建议:

使用异步发送,并且producer实例只需要3 ~ 5个即可 对每一个producer 调用 setInstanceName,区别不同的生产者。

6)发送超时时间

当客户端向broker发送请求超时时,客户端会抛出 RemotingTimeoutException,默认的超时时间是3秒。通过调用send(msg, timeout) 可以设置超时时间。超时时间建议不要设置过小,因为 broker 可能需要时间刷盘或向 slave 同步数据。

7)对于同一个应用最好只使用一个Topic,消息的子类型可以使用 tags 来标识,tags 可以由应用自由设置。当发送的消息设置了 tags 时,消费方在订阅消息时可以使用 tags 在 broker 做消息过滤。注意这里的命名虽然是复数,但是一条消息只能有一个tag。

8)消息在业务层面的唯一标识可以设置到 keys 字段,方便根据 keys 来定位消息。broker 会为每个消息创建索引(哈希索引),应用可以通过topic 、key 查询这条消息的内容(MessageExt),以及消息被谁消费(MessageTrack,精确到consumer group)。由于是哈希索引,请尽量保证key 的唯一,这样可以避免潜在的哈希冲突。

9)消息发送不管是成功还是失败都要打印消息日志,日志内容务必包含 sendResult 和 key 字段。

10)对于消息不可丢失的应用,务必要有消息重发机制。例如如果消息发送失败,可以将消息存储到数据库,然后通过定时程序或者人工的方式触发重发。

11)调用send 同步发送消息时,假定此时设置了 isWaitStoreMsgOK=true(default is true),只要不抛出异常就代表发送成功,但当 isWaitStoreMsgOK = false 时,发送永远返回 SEND_OK。但是对于发送“成功”会有多个状态,在 SendStatus 中定义如下:

FLUSH_DISK_TIMEOUT

如果 broker 设置的 FlushDiskType = SYNC_FLUSH,当 broker 的在刷盘超时时(MessageStoreConfig.syncFlushTimeout,默认5秒)会返回该状态。此时消息任然保存在内存中,只有broker 宕机时消息才会丢失。

FLUSH_SLAVE_TIMEOU

如果 broker 的 role 是 SYNC_MASTER,当 slave 同步数据的时间超过了 MessageStoreConfig.syncFlushTimeout (默认5秒) 时会返回此状态。此时只有主从都宕机,并且主也没有刷盘时,消息才会丢失。

SLAVE_NOT_AVAILABLE

如果 broker 的 role 是 SYNC_MASTER,并且此时 slave 不可用时会返回该状态。

SEND_OK

发送成功。为了保证消息不丢失还需要配置 SYNC_MASTER or SYNC_FLUSH。

12)消息重复

当发送消息时返回 FLUSH_DISK_TIMEOUT/FLUSH_SLAVE_TIMEOUT,若非常不幸的 broker 也宕机了,消息将会丢失。此时如果什么都不做,消息可能会丢失,如果重发消息,消息可能会出现重复。

通常我们建议发送端重发消息,由消费方来保证消息消费的幂等性。

1.2 消息发送失败如何处理

Producer 的 send 方法本生支持内部重试,重试逻辑如下:

至多重试3次 如果发送失败,则轮转到下一个broker 这个方法的总耗时时间不超过 sendMsgTimeout,默认3秒 所以发送消息已经产生超时异常的话就不会再重试。以上策略仍不能保证消息发送一定成功,为保证消息发送一定成功,建议应用这么做:如果调用 send 同步发送失败,则尝试将消息存储到db,由后台线程定时重试,保证消息一定到达 Broker。

1.3 oneway 的发送形式

对于可靠性要求不高的应用,可以采用 oneway 的发送形式,oneway 形式不等待应答。

1.4 发送顺序消息

顺序消息分为分区有序和全局有序。

分区有序要求 producer 在send 时传入 MessageQueueSelector 的实现类,最终将某一类消息发送到同一队列。但是一旦发生通信异常、broker 重启等,由于队列总数发生变化,哈希取模后定位的队列会变化,会产生短暂的顺序不一致。如果业务能容忍在集群异常情况下(如某个 broker 宕机或者重启)消息短暂的乱序,使用分区有序比较合适。

全局严格有序的消息即便在异常情况下也能保证消息的有序性,但是却牺牲了分布式的 failover 特性,即 broker 集群中只有要一台机器不可用,则整个集群都不可用,服务可用性会大大降低。

顺序消息的缺点:

发送顺序消息无法利用集群的 FailOver 特性 消费顺序消息的并行度依赖于队列数量 队列热点问题,个别队列由于哈希不均导致消息过多,消费速度跟不上,产生消费堆积问题 遇到消费失败的消息,无法跳过,当前队列需要暂停 5.发送事务消息 目前暂不支持。

二. 消费者

2.1 消费者组和订阅

不同的消费者组可以独立消费相同的topic,这点类似于ActiveMQ的虚拟 topic. 另外对于相同的消费者组,需要确保组内的消费者订阅消息的规则是一致的!

MQ 里的一个Consumer Group 代表一个 Consumer 实例群组。对于大多数分布式应用来说,一个 Consumer Group 下通常会挂载多个 Consumer 实例。订阅关系一致指的是同一个 Consumer Group 下所有 Consumer 实例的处理逻辑必须完全一致。一旦订阅关系不一致,消息消费的逻辑就会混乱,甚至导致消息丢失。

由于 MQ 的订阅关系主要由 Topic+Tag 共同组成,因此,保持订阅关系一致意味着同一个 Consumer Group 下所有的实例需在以下两方面均保持一致:

订阅的 Topic 必须一致;订阅的 Topic 中的 Tag 必须一致。

技术架构 > Consumer 最佳实践 > image2017-11-15 15:50:13.png

2.2 MessageListener

1)顺序消费 MessageListenerOrderly

顺序消费时消费者会锁定队列,以确保消息被顺序消费,但是这样也会造成一定的性能损耗。当消费出现异常的时候,建议不要抛出异常,而是返回 ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT,让消费暂停一会,暂停时间由 context.setSuspendCurrentQueueTimeMillis 方法指定。

2)并发消费

并发消费是推荐的消费方式,在此种模式下,消息将被并发的消费。消费出现异常时不建议抛出异常,只需要返回 ConsumeConcurrentlyStatus.RECONSUME_LATER 即可。为了保证消息肯定被至少消费一次,消息将会被重发回 broker (topic不是原topic而是这个消费组的RETRY topic),在延迟的某个时间点(默认是10秒,业务可设置,通过 delayLevelWhenNextConsume 和 MessageStoreConfig.messageDelayLevel 设置)后,再次投递到这个 ConsumerGroup,而如果一直这样重复消费都持续失败到一定次数(默认是16次,DefaultMQPushConsumer.maxReconsumeTimes),就会投递到DLQ队列。应用可以监控死信队列来做人工干预。

3)返回状态

在并行消费时可以通过返回 RECONSUME_LATER 来告诉 Consumer 当前无法消费该消息,等延时一段时间再重新消费,但是此时消费不会停止,你可以继续消费其他消息。但在顺序消费时,因为要保证消费的顺序性,所以你不能跳过失败的消息,此时你可以通过返回 SUSPEND_CURRENT_QUEUE_A_MOMENT 来告诉 Consumer 先暂停一会。

4)阻塞

不建议阻塞Listener,因为这会阻塞住线程池,同时也有可能造成消费者线程终止。

2.3 线程数

consumer 内部通过一个 ThreadPoolExecutor 来消费消息,可以通过 setConsumeThreadMin 和 setConsumeThreadMax 来改变线程池的大小。

2.4 ConsumeFromWhere

当新实例启动的时候,PushConsumer会拿到本消费组broker已经记录好的消费进度(consumer offset),按照这个进度发起自己的第一次Pull请求。

如果这个消费进度在Broker并没有存储起来,证明这个是一个全新的消费组,这时候客户端有几个策略可以选择:

CONSUME_FROM_LAST_OFFSET //默认策略,从该队列最尾开始消费,即跳过历史消息。

CONSUME_FROM_FIRST_OFFSET //从队列最开始开始消费,即历史消息(还储存在broker的)全部消费一遍。

CONSUME_FROM_TIMESTAMP//从某个时间点开始消费,和setConsumeTimestamp()配合使用,默认是半个小时以前 注意:这些配置只对全新的消费组有效,老的消费组都是按已经存储过的消费进度继续消费。

对于老消费组想跳过历史消息可以采用以下几种方法:

1)判断消息的发送时间,太老的消息直接返回 CONSUME_SUCCESS。

2)判断消息的 offset 和 MAX_OFFSET 的差距,如果落后太多,可以直接。返回 CONSUME_SUCCESS。

3)消费者启动前,先调整该消费组的消费进度,再开始消费。可以人工使用命令 resetOffsetByTimeStamp,详见 ResetOffsetByTimeCommand.java。

2.5 消息幂等

由于 RocketMQ 无法避免消费重复,所以如果业务对消息重复非常敏感,务必在业务层面去重。

2.6 消费速度慢处理方式

1)提高消费并行度

大部分消息消费行为都属于 IO 密集型业务,适当的提高并发度可以显著的改善消费的吞吐量。

2)批量方式消费

默认情况下 consumer 的 consumeMessageBatchMaxSize 为1,即一次只消费一个消息,如果应用可以批量消费消息,则可以很大程度上提高消费吞吐量。

3)跳过非重要消息

当消堆积严重时可以丢弃不重要的消息。

4)优化消息消费过程

2.7 打印消费日志

建议在消费入口方法打印消息,方便后续排查问题,消费失败时也打印失败日志。

2.8 利用broker过滤消息,避免多余的消息传输

三. 小结

好了,RocketMQ生产者与消费者的使用事项就总结完毕了,相信大家对RocketMQ的使用应该会更有信心了。

 

RocketMQ发送和接收方式详解 在使用 RocketMQ 进行消息发送时,可以根据不同的发送需求选择合适的发送方式。异步发送是指消息发送方发送消息后,不会立即等待服务器的响应,而是提供一个回调接口,服务器响应时通过回调接口来通知发送方。单向发送是指消息发送方只负责发送消息,不等待服务器的响应也不关心消息是否被服务器接收,适用于对可靠性要求不高的场景。集群消费模式下,同一个消费者组中的多个消费者实例共同消费主题下的消息,每条消息只会被消费一次。延迟消费不是通过消费者的特定设置来实现的,而是在发送消息时设置消息的延迟等级。 阅读详情

相关推荐

学会了,SpringCloud+RocketMQ实现分布式事务

随着互联网公司的微服务越来越多,分布式事务已经成为了我们的经常使用的。所以我们来一步一步的实现基于RocketMQ的分布式事务。接下来,我们将要做的主题写出来。 RocketMQ的分布式事务结构和说明 搭建RocketMQ步骤 事务场景,然后准备工程,运行代码   一、RocketMQ的分布式事务结构和说明   我们通过下图来了解一下RocketMQ实现分布式事务的结构。采用半消息机制实现分布式事务,半消息顾名思义,就是发送方将消息发送到MQ中的Broker端,这个消息被标记

a1472750149的博客 748

RocketMq-RocketMQMessageListener标签解析

rocketmq结合springboot使用起来十分方便,只要我们将实现类添加注解RocketMQMessageListener,并且实现接口RocketMQListener,就可以轻松实现某topic的消费侧消费消息的功能。

weixin_41953346的博客 6631

RocketMQ 三种消息发送方式

producer向broker发送消息时指定消息发送成功及发送异常的回调方法,调用API后立即返回,producer发送消息线程不阻塞,消息发送成功或失败的回调任务在一个新的线程中执行。发送消息前进行校验,比如消息的内容长度不能为0、消息最大长度、消息必要的属性是否具备等(topic、消息体,生产组等)。Producer按选择算法从以上队列中选择一个进行消息发送,如果发送消息失败则在下次选择的时候会规避掉失败的broker。主题下的一条消息能被消费组下的所有消费者消费。.........

流楚丶格念的博客 8109

RocketMQ消息队列-@RocketMQMessageListener实现原理

相当于定义一个消费者,定义了消费者的一些属性实现接口来处理具体消费逻辑每个消费者初始化了一个对象,该对象中包含消费实例和消费者的属性服务启动的时候开启一个线程轮训队列中的消息,如果没有就一直阻塞,拿到消息后,最终会调用自己实现的onMessage方法。

Apandam的博客 1万+

全志T133-s3(Tina Linux)下RTL8723DS WiFi驱动移植与调试实战

本文详细介绍了在全志T133-s3平台(Tina Linux)上移植RTL8723DS WiFi驱动的完整流程,包括硬件连接、驱动源码获取、内核配置、系统适配、设备树配置以及常见问题排查。通过实战案例,帮助开发者快速解决SDIO接口通信、固件加载、电源管理等关键问题,实现稳定的WiFi功能。

weixin_30505225的博客 507

协方差矩阵

对两个类内协方差矩阵进行对角化,可以将它们变换为对角矩阵。这个过程可以通过对每个协方差矩阵进行特征值分解来实现,从而得到它们的特征向量和特征值,进而得到它们的对角矩阵形式。这个过程的意义在于,它可以帮助我们找到一个新的坐标系,使得在这个坐标系下,每个特征之间都是独立的,从而简化了计算。具体来说,当我们使用对角协方差矩阵作为特征向量的坐标系时,它意味着每个特征之间都是相互独立的,从而方便了进一步的分析和处理。在实际应用中,对角化协方差矩阵可以用于降维、特征选择和分类等任务。

m0_55196097的博客 1万+

RocketMQ从零到学会使用

1. 相关概念及安装 1.1 MQ基本概念 消息队列(MQ:Message Queue)是以一种用来保存消息数据的队列。 调用:web层代码调用service层代码时调用;请求响应可以称之为调用;这些调用多是同步的,调用方需要等待被调用方给出结果之后,才能继续执行后面的代码。 消息:调用者发送给被调用者,需要后者处理的内容。包括但不仅限于(eg:)web层发送给service层需要其保存的数据对象。 队列:数据结构的一种,特征:先进先出,FIFO。 MQ系统中包含如下角色和概念: 生产者(

m0_59849460的博客 2万+

VOWIFI--相关的协议文档

一、3GPP相关协议文档 3GPP 23.402 Architecture enhancements for non-3GPP accesse- //重要 整体框架结构和流程,3GPP和NON-3GPP切换 3GPP 36.304  User Equipment (UE) procedures in idle mode //重要,终端在空闲状态下3GPP与NON-3GPP之间的重选方法   3GP

时九博客 3581

菜鸟也能学会RocketMq

菜鸟也能学会RocketMqRocketMq是什么选择RocketMQ的理由:Windows下开发环境搭建代码实战启动服务器生产者实现消费者实现 RocketMq是什么 RocketMQ 是一款分布式、队列模型的消息中间件,具有以下特点: 能够保证严格的消息顺序 提供丰富的消息拉取模式 高效的订阅者水平扩展能力 实时的消息订阅机制 亿级消息堆积能力 选择RocketMQ的理由: 强调集群模式无单点,可扩展,任意一点高可用,水平扩展 海量数据的堆积能力,消息堆积后,写入延迟低 支持上万个队列 消息失败重试机制

qq_31567831的博客 458

从SSTS到CTS:解码汽车电子架构中的需求与实现规范

本文深入解析汽车电子架构中SSTS(子系统功能规范)与CTS(零部件技术规范)的转换过程,揭示从抽象需求到物理实现的关键步骤。通过实际案例说明如何将SSTS的功能逻辑、接口定义和性能指标转化为具体的CTS实施方案,并分享多供应商协同与测试验证的最佳实践,帮助开发者高效完成汽车电子系统开发。

weixin_29201859的博客 500

2023年全国职业院校技能大赛高职组“区块链技术应用”赛项赛卷(3卷)解析

我们先绘制题组中所有设计图我这边作图用的国内的在线作图工具。

2301_76737000的博客 5421

学会RocketMQ这一篇就够了

RocketMQ简介 RocketMQ是由阿里捐赠给Apache的一款低延迟、高并发、高可用、高可靠的分布式消息中间件。经历 了淘宝双十一的洗礼。RocketMQ既可为分布式应用系统提供异步解耦和削峰填谷的能力,同时也具备 互联网应用所需的海量消息堆积、高吞吐、可靠重试等特性。 官方文档: https://rocketmq.apache.org/docs/quick-start/ github中文主页:https://github.com/apache/rocketmq/tree/master/docs/c

yiqiu1959的博客 1411

Unity 2D精灵点击交互实现:从BoxCollider 2D到Event Trigger的完整指南

本文提供了Unity 2D精灵点击交互的完整实现指南。通过详细拆解BoxCollider 2D与Event Trigger两大核心组件的协同工作原理,手把手教你为Sprite Renderer添加点击、悬停等事件响应。文章包含从基础配置到进阶优化、性能调试的实战步骤,帮助开发者高效实现游戏世界内的对象交互,是Unity 2D开发的实用教程。

ansible6ops的博客 303

5分钟学会RocketMQ

RocketMQ 简介 RocketMQ 是一个队列模型的消息中间件,具有高性能,高可用,高实时等特性,它并不支持JMS(java消息服务)规范,但参考了JMS规范和kafak等的思想。 Producer 、Consumer,队列都可以分布式。 Producer可以向队列轮流发送消息,队列的集合称为Topic,Consumer可以做广播消费,也可以做集群消费。 能够保证严格的消息顺序 提供消费者水平订阅扩展能力 亿级的消息堆积能力 较少的依赖

lgxzzz的博客 250

CRMEB开源电商系统 /api/products SQL注入漏洞复现(CVE-2024-36837)

2024年6月,CRMEB开源电商系统发布了新补丁,修复了一处SQL注入漏洞(CVE-2024-36837)。经分析,该漏洞可以通过请求api的路径接口来进行SQL注入,进而可能导致敏感信息泄露,该注入可暴露后台web绝对路径,深入利用可获取服务器权限,该漏洞无前置条件且利用简单,建议受影响的用户尽快修复漏洞。

0xSec 2885

在RStudio中使用GitHub Copilot:代码自动生成,从此告别手敲!

可以通过自定义提示词来引导Copilot生成符合自己需求的代码。再看一个做统计分析的。

Codewar的博客 334

docker安装rocketmq你学会了吗

防火墙开通端口 9876 10911 9800 firewall-cmd --zone=public --add-port=9876/tcp --permanent firewall-cmd --zone=public --add-port=10911/tcp --permanent firewall-cmd --zone=public --add-port=9800/t...

小泽 296

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

三分钟学会spring boot整合rocketmq

RocketMQ部署 1.下载 1.1地址:http://rocketmq.apache.org/release_notes/release-notes-4.2.0/ 1.2选择‘Binary’进行下载 1.3解压已下载工程 配置 2.1 系统环境变量配置 变量名:ROCKETMQ_HOME 变量值:MQ解压路径\MQ文件夹名 重启服务器 启动 3.1...

longzhongxiaoniao的博客 4800

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

读完 RocketMQ 源码,我学会了如何优雅的创建线程

本文是RocketMQ 系列文章的开篇,和朋友们简单聊聊 RocketMQ 源码里创建线程的技巧。单线程抽象类 ServiceThread使用者只需要实现业务逻辑以及定义线程名即可 ,不需要写冗余的代码。线程池封装适当封装,定义线程工厂,并合理配置线程池参数。线程名很重要文件日志,堆栈记录配合线程名能大大提升解决问题的效率。RocketMQ 的多线程编程技巧很多,比如线程通讯,并发控制,线程模型等等,后续的文章会一一为大家展现。

m0_73088370的博客 498

读 RocketMQ 源码学会如何优雅的创建线程

创建单线程单线程抽象类线程池原理线程池封装线程名很重要总结RocketMQ 是一款由阿里巴巴集团开源的分布式消息系统。它基于高可用分布式集群技术,提供低延时、高可靠的消息发布与订阅服务。RocketMQ 的主要特点之一是其高可靠性和强大的容错能力,在分布式架构中表现出色。它还具有高度的可扩展性,可以与各种数据存储技术集成,并且可以适应各种复杂的应用程序场景。在本文中,笔者将以 RocketMQ 源码中创建线程的几点技巧为例,深入探讨 RocketMQ 的架构和技术原理。

2301_76936922的博客 234
上一篇: 一文理解分布式开发中的服务治理
下一篇: 数据接入平台(DIP)系列文章之一|功能及架构浅析
程序员职业指南
博客等级 码龄4年 2138粉丝 960原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值