常见问题

快速开始

… 消息队列 RocketMQ 是否可以在公网访问?

支持,消息队列 RocketMQ 专门开辟了公网专用集群供测试使用。 在消息队列 RocketMQ 的控制台创建 Topic 时,Region 请选择“公网”。 此 Topic 即可通过公网访问,但公网的网络环境复杂,相对没有内网更稳定。

当正式投入生产时,务必使用可用性更高的生产环境 Region,部署在阿里云 ECS 上进行收发消息。

… 新创建的 Group ID 从哪里开始消费?
  • 如果这个 Group ID 是第一次启动,则会忽略启动之前发送的消息,也就是忽略历史消息,从启动之后发送的消息开始消费。

  • 如果这个 Group ID 是第二次启动,那么从上次消费的位置开始消费。

  • 如果想从特定位置开始消费,可以通过消息队列 RocketMQ 控制台的消费位点重置功能, 指定到具体的时间开始消费。每次重置只针对特定 Group ID 下的特定 Topic,不会影响其他 Group ID。

… 消息队列 RocketMQ 消费失败如何重新消费消息?

集群消费方式

消费业务逻辑代码如果返回 Action.ReconsumerLater,或者 NULL,或者抛出异常,消息都会走重试流程,至多重试 16 次,如果重试 16 次后,仍然失败,则消息丢弃。每次重试的间隔时间如下:

第几次重试

每次重试间隔时间

1

10 秒

2

30 秒

3

1 分钟

4

2 分钟

5

3 分钟

6

4 分钟

7

5 分钟

8

6 分钟

9

7 分钟

10

8 分钟

11

9 分钟

12

10 分钟

13

20 分钟

14

30 分钟

15

1 小时

16

2 小时

可以通过调用 message.getReconsumeTimes() 方法来获取消息的重试次数。

广播消费方式

广播消费方式仍然能保证一条消息至少被消费一次,但消费失败后不做重试操作。

… 消息发送了,但是没有收到怎么办?

消息队列 RocketMQ 提供了多种消息查询方式:

  1. 使用 Topic 按时间范围进行查询,可以查询到一段时间内某 Topic 收到的所有消息。

  2. 使用 Topic 和 Message ID 对消息进行精准查询。

  3. 使用 Topic 和 Message Key 较为精准地查询具有相同 Message Key 的一类消息。

上述方式可以查询到消息的具体内容以及消费情况, 如果需要追踪一条消息从生产者发出到被消费者消费的整个链路中各个相关节点的时间地点, 可以使用消息队列 RocketMQ 最新的消息轨迹查询功能,具体使用方式请参考消息轨迹使用指南。

… 消息队列 RocketMQ 是否能保证消息不重复?

绝大多数情况下,消息是不重复的。作为一款分布式消息中间件,在网络抖动、应用处理超时等异常情况下,无法保证消息不重复,但是能保证消息不丢失。

… 控制台显示的消息堆积量是否包含了 Topic 下所有 Tag 的消息?

是。消息生产者将所有类型的 Tag 都发送至同一个 Topic 中,消息按照先后顺序在队列中排列, 并维护一个消息写入位点;Group ID 启动时会指明需要订阅的 Tag,并从服务端获取当前的消费位点; 服务端从当前 Group ID 的消费位点开始遍历队列中的消息, 判断如果消息的 Tag 符合 Group ID 订阅的 Tag 即投递给 Group ID,不符合则跳过该消息。

如下图所示,Group ID 消费位点往前移动,Tag2、Tag3 的消息会在服务端被过滤掉, Tag1 的消息为 Group ID 所需要的,会投递给 Group ID。

tag-accumulation

因此您在控制台的 消费者状态 > 消息堆积总量 看到的是未被过滤的堆积总量,包含了所有 Tag 的消息量。

配置相关

… 消息队列 RocketMQ 消息在服务器保存多长时间?

存储的消息最多保存 3 天,超过 3 天未消费的消息会被删除。建议配置监控报警实时监控消费进度,并根据报警信息人工介入处理。

… 消息队列 RocketMQ 消息 Body 的长度限制是多少?

消息大小根据消息类型来限制。具体限制如下所述:

  • 普通消息和顺序消息:4 MB

  • 事务消息和定时/延时消息:64 KB

… 消息队列 RocketMQ 客户端如何设置消费线程数?

在启动 Consumer 时,设置一个 ConsumeThreadNums 属性即可。具体示例如下所示:

public static void main(String[] args) {
    Properties properties = new Properties();
    properties.put(PropertyKeyConst.GROUP_ID, "GID_001");
    properties.put(PropertyKeyConst.AccessKey, "xxxxxxxxxxxx");
    properties.put(PropertyKeyConst.SecretKey, "xxxxxxxxxxxx");
    /**
    * 设置消费端线程数固定为 20
    */
    properties.put(PropertyKeyConst.ConsumeThreadNums,20);
    Consumer consumer =ONSFactory.createConsumer(properties);
    consumer.subscribe("TestTopic", "*", new MessageListener() {
        public Action consume(Message message, ConsumeContext context) {
            System.out.println("Receive: " + message);
            return Action.CommitMessage;
        }
    });
    consumer.start();
    System.out.println("Consumer Started");
}
… 由于.NET 客户端的配置问题,导致 dll 加载失败或者其他运行错误时如何处理?

请参考.NET SDK 压缩包中的文档:SDK_GUIDE.pdf,确认工程配置与文档说明一致。

消息轨迹

… 为什么查询不到轨迹数据?

当输入查询条件查不到轨迹数据时,请参考是否属于以下无法查询情况。

  1. 消息轨迹目前支持 Java 客户端(版本至少为 1.2.2)。

  2. 查询条件是否正确,如 Topic、Message ID、Message Key 是否输入正确。

  3. 查询时间区间是否正确,为了提高查询速度,需要您输入消息的发送时间范围。如果查询不到,请尝试扩大时间范围重试。

  4. 如果确认上述情况无误还是无法查询到结果,请提交工单获得技术支持,并附带上日志文件,日志文件位于/home/{user}/logs/ons.log。

… 确定已经消费了消息,但轨迹却显示没有消费,而且客户端 IP 和 Producer ID 不符合实际情况?

出现该现象是由于客户端本身并没有升级到支持轨迹功能的版本, 因此消息队列 RocketMQ 轨迹查询后端仅仅能够拿到部分不完整的轨迹数据, 展现结果不正常。建议尽快升级客户端,详情请参考消息轨迹使用指南。

… 消费者列表中为什么没有我的 Group ID?

出现该情况的原因可能是消息的下游订阅方太多,轨迹图中空间有限,请将鼠标放在滚动条位置,滚动查看完整数据。

… 之前的查询任务怎么看不到了?

为了防止历史查询任务太多,影响展示效果,消息队列 RocketMQ 会对用户的历史查询任务做定期清理, 默认只保留 7 天以内的查询任务,如果出现历史任务看不到,请重新查询即可。

告警处理

… 收到订阅关系不一致告警后怎么办?

… 消息队列 RocketMQ 如何添加消费堆积告警?

登录消息队列 RocketMQ 控制台。

  1. 在左侧菜单栏选择监控报警。

  2. 单击页面右上角新增监控项,选择需要报警的 Group ID 与 Topic,设置报警阈值以及报警人信息即可完成报警项设置。

  3. 更多详细信息请参考监控报警。

… 消息队列 RocketMQ 用户收到堆积告警后怎么办?

问题确认

登录消息队列 RocketMQ 控制台,选择 Group 管理 > 消费者状态,堆积量栏的值高于预期。

登录消息队列 RocketMQ 控制台,选择消息轨迹 > 创建查询任务 > 按 Message ID 查询, 部分消息已发送至 Broker,但未投递给下游消费者。

问题分析

消息队列 RocketMQ 的消息发送至 Broker 后,配置了 Group ID 的客户端根据当前的消费位点从 Broker 拉取部分消息到本地进行消费。 消费过程中访问共享资源加锁、I/O 和网络资源争抢、HTTP 调用未设置超时时间等原因,都会导致单条消息的消费时间很长,消息开始在服务端堆积。

解决方案

请按照如下方法排查并解决问题:

登录消息队列 RocketMQ 控制台,选择资源报表 > 消息消费,查询历史消费记录。 如果消息写入速度大于消息消费速度,调整业务代码或对消费者进行扩容。

在应用打印 Jstack 信息 jstack -l {pid} | grep ConsumeMessageThread。 如果有消息阻塞现象,连续打印 5 次 Jstack 信息,确认消费线程卡在哪里,解决后可尝试重启应用观察消费是否恢复。

如果消息已经没有堆积,检查阈值是否设置过小导致消息堆积,单击监控报警,单击编辑,增大消息堆积的报警阈值。

结果验证

在应用打印 Jstack 信息 jstack -l {pid} | grep ConsumeMessageThread,无消费线程阻塞现象。

登录消息队列 RocketMQ 控制台,选择 Group 管理 > 消费者状态,消费 TPS 栏的值上升,堆积量栏的值下降。

顺序消息

… 顺序消息是否支持集群消费和广播消费?

顺序消息支持集群消费,不支持广播消费。

… 同一条消息是否可以既是顺序消息,同时又支持定时消息和事务消息?

不行。顺序消息、定时消息、事务消息是不同的消息类型,三者是互斥关系,不能叠加在一起使用。

… 顺序消息支持哪些 Region?

支持消息队列 RocketMQ 所有公共云 Region 和金融云 Region。

… 顺序消息的使用范围是什么?

关于顺序消息的使用范围,包括适用场景和使用限制等,请参见顺序消息。

… 为什么全局顺序消息性能一般?

全局顺序消息是严格按照 FIFO 的消息阻塞原则,即上一条消息没有被成功消息, 那么下一条消息会一直被存储到 Topic 队列中。如果想提高全局顺序消息的 TPS, 可以升级实例配置,同时消息客户端应用尽量减少处理本地业务逻辑的耗时。

… 顺序消息支持哪种消息发送方式?

顺序消息只支持可靠同步发送方式。

消息堆积

… 如何处理消息堆积?

除了异步解耦功能,消息队列 RocketMQ 还有挡住前端数据洪峰的重要功能,以此保证后端系统的稳定性。 这要求消息队列 RocketMQ 具有一定的消息堆积能力。消息队列 RocketMQ 能支持 10 亿级别的消息堆积,不会因为消息堆积导致性能明显下降。

问题描述

在消息队列 RocketMQ 控制台的消费者状态页面,看到 Group ID 的实时消息堆积量的值高于预期,且性能明显下降。

解决方法

面对消息堆积,且有明显性能下降的情况,可采取以下措施处理:

  1. 在消息队列 RocketMQ 控制台,通过查看消费者状态获取消息堆积的消费者实例所对应的宿主机 IP,并登录该宿主机或容器。

  2. 执行以下任一命令查看进程 pid:

    ps -ef |grep java
    jps -lm
    
  3. 执行以下命令查看堆栈信息:

    jstack -l pid > /tmp/pid.jstack
    
  4. 执行以下命令查看 ConsumeMessageThread 的信息,重点关注线程的状态及堆栈:

    cat /tmp/pid.jstack|grep ConsumeMessageThread -A 10 --color
    

    命令回显如下图所示。

    命令回显

线程状态的解释说明请参见 Java 官方文档。

更多信息

如按以上操作还未解决因消息堆积而导致的性能下降问题,请提交工单。提交时,请附带以下信息:

  • heap.bin 文件

    该文件可通过执行 jmap -dump:format=b,file=heap.bin [pid] 命令获取,再执行 gzip heap.bin 命令生成压缩包。 [pid] 是消息堆积处理第一步中找到的进程 pid。

  • 发生消息堆积的消费者客户端ons.log本地日志

  • 消费者客户端的版本