全部产品
云市场

状态不一致

更新时间:2020-01-14 15:36:02

本文将介绍常见的状态不一致问题及相应的解决方案。

非预期的客户端连接

现象:

  • 用户侧反馈部分消息发送后未收到。登录消息队列控制台。点击 消息轨迹 > 创建查询任务 > 按 Message ID 查询,发现部分消息已发送至 broker,但未投递给下游消费者。
  • 登录消息队列控制台。点击 Group 管理 > 消费者状态,连接状态栏下方出现不在预期范围内的客户端 IP,同时存在部分消息堆积只在非预期范围内的客户端上。

分析:

  • 原因
    在同—套环境中,以错误的方式(AccessKeyId、AccessKeySecret、Topic 等信息配置错误)启动了 Group ID 的客户端,导致该客户端进程占用了 Topic 下的部分消息队列而无法正确消费消息,消息在服务端堆积,无法实时投递给下游正确的消费者。

  • 确认方式
    先根据连接状态定位有问题的进程,然后通过 /{user.home}/logs/sofamq.log 以及程序代码确认配置的 AK、SK、Topic 等信息。

  • 恢复方法
    可以先将有问题的客户端进程先关闭,此时之前堆积的消息会立马进行 Rebalance 投递至正常的客户端,待定位到问题修复后再重启有问题的进程。(快速恢复)

验证:

  1. 登录消息队列控制台。
  2. 选择 Group 管理 > 消费者状态。连接状态栏下方显示的所有已连接的客户端都能在预期范围内,并能正常消费消息。同时订阅关系是否一致栏显示是。

消息不合法

可能产生的原因:一般是消息属性、消息内容不合法,不合法的情况有:

  • 消息为空;
  • 消息内容为空;
  • 消息内容长度为 0;
  • 消息内容超过限定长度。

建议解决方案
请确保消息没有以上的不合法情况,并根据异常提示进行解决。

参数不合法

可能产生的原因:参数不合法的情况有以下几种:

嵌套的异常说明 异常描述
consumeThreadMin Out of range [1, 1000] 消费端线程数设置不合理
consumeThreadMax Out of range [1, 1000] 消费端线程数设置不合理
messageListener is null 未设置 messageListener
consumerGroup is null 未设置 Group ID
msg delay time more than 40 day 定时消息延时不能超过 40 天

建议解决方案
按如下步骤操作:

  1. 按照异常提示修改客户端对应参数的配置,确保其在合理范围内。
  2. 重启应用。

客户端状态异常

可能产生的原因

  • 创建 Consumer、Producer 之后未调用 start() 方法来启动客户端;
  • 创建 Consumer、Producer 之后 start() 过程有异常导致客户端启动失败;
  • 创建 Consumer、Producer 并成功调用 start() 方法后,显示调用了 shutdown() 方法关闭了客户端。

建议解决方案
按如下步骤操作:

  1. 确保创建 Consumer、Producer 之后调用 start() 保证客户端处于启动状态;
  2. 查看 ons.log 判断在客户端在启动过程中是否有异常。

订阅关系不一致

原因描述

在不同的 JVM 中启动了多个 Consumer,并且给相同的 Group ID 配置了不同的 Topic,或者是相同的 Topic 但 Tag 不同,最终导致订阅关系不一致,消息不符合预期。

  • 错误示例一:同一个 Group ID(GID-MQ-FAQ)订阅的 Topic 不同(分别是 MQ-FAQ-TOPIC-1、MQ-FAQ-TOPIC-2)。
    JVM-1上的代码:

    1. Properties properties = new Properties();
    2. properties.put(PropertyKeyConst.GROUP_ID, "GID-MQ-FAQ");
    3. Consumer consumer = ONSFactory.createConsumer(properties);
    4. consumer.subscribe("MQ-FAQ-TOPIC-1", "NM-MQ-FAQ", new MessageListener() {
    5. public Action consume(Message message, ConsumeContext context) {
    6. System.out.println("Receive: " + message);
    7. return Action.CommitMessage;
    8. }
    9. });
    10. consumer.start();

    JVM-2上的代码:

    1. Properties properties = new Properties();
    2. properties.put(PropertyKeyConst.GROUP_ID, "GID-MQ-FAQ");
    3. Consumer consumer = ONSFactory.createConsumer(properties);
    4. consumer.subscribe("MQ-FAQ-TOPIC-2", "NM-MQ-FAQ", new MessageListener() {
    5. public Action consume(Message message, ConsumeContext context) {
    6. System.out.println("Receive: " + message);
    7. return Action.CommitMessage;
    8. }
    9. });
    10. consumer.start();
  • 错误示例二:同一 Group ID(GID-MQ-FAQ)订阅的 Topic 相同,但 Tag 不同(分别 NM-MQ-FAQ-1、NM-MQ-FAQ-2)。
    JVM-1上的代码:

    1. Properties properties = new Properties();
    2. properties.put(PropertyKeyConst.GROUP_ID, "GID-MQ-FAQ");
    3. Consumer consumer = ONSFactory.createConsumer(properties);
    4. consumer.subscribe("MQ-FAQ-TOPIC-1", "NM-MQ-FAQ-1", new MessageListener() {
    5. public Action consume(Message message, ConsumeContext context) {
    6. System.out.println("Receive: " + message);
    7. return Action.CommitMessage;
    8. }
    9. });
    10. consumer.start();

    JVM-2上的代码:

    1. Properties properties = new Properties();
    2. properties.put(PropertyKeyConst.GROUP_ID, "GID-MQ-FAQ");
    3. Consumer consumer = ONSFactory.createConsumer(properties);
    4. consumer.subscribe("MQ-FAQ-TOPIC-1", "NM-MQ-FAQ-2", new MessageListener() {
    5. public Action consume(Message message, ConsumeContext context) {
    6. System.out.println("Receive: " + message);
    7. return Action.CommitMessage;
    8. }
    9. });
    10. consumer.start();

建议解决方案
请确保在不同 JVM 中使用相同的 Group ID 启动多个 Consumer 时,配置的 Topic 和 Tag 是一致的。