本文将介绍常见的状态不一致问题及相应的解决方案。
非预期的客户端连接
现象:
部分消息发送后客户端未收到。按 Message ID 查询消息(具体操作方法详见 消息查询)后,发现部分消息已发送至 Broker,但未投递给下游消费者。
查看目标 Group ID 的消费者状态(具体操作方法详见 查看消费者状态),连接信息中出现了不在预期范围内的客户端 IP,同时存在部分消息只堆积在非预期范围内的客户端上的情况。
可能的原因:
以错误的方式(AccessKeyId、AccessKeySecret、Topic 等信息配置错误)启动了 Group ID 的客户端,导致该客户端进程占用了 Topic 下的部分消息队列而无法正确消费消息,消息在服务端堆积,无法实时投递给下游正确的消费者。
解决方案:
先根据连接状态定位有问题的进程,然后查看
/{user.home}/logs/sofamq.log
日志以及程序代码确认配置的 AK、SK、Topic 等信息是否配置正确。快速恢复。
将有问题的客户端进程先关闭,此时之前堆积的消息会马上进行 Rebalance 投递至正常的客户端,待问题修复后再重启有问题的进程。
结果验证:
登录消息队列控制台查看目标 Group ID 的消费者状态,确认连接信息中显示的所有已连接的客户端都能在预期范围内,并能正常消费消息。同时订阅关系一致栏显示 是。
消息不合法
可能的原因:
消息属性、消息内容不合法,有以下 4 种情况:
消息为空。
消息内容为空。
消息内容长度为 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 天 |
解决方案:
请确认客户端对应参数没有以上不合法情况,并根据异常提示进行解决。
重启应用。
客户端状态异常
可能的原因:
创建 Consumer、Producer 之后未调用
start()
方法启动客户端。创建 Consumer、Producer 之后
start()
过程有异常导致客户端启动失败。创建 Consumer、Producer 并成功调用
start()
方法后,显示调用了shutdown()
方法关闭了客户端。
解决方案:
查看 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上的代码示例如下:
Properties properties = new Properties(); properties.put(PropertyKeyConst.GROUP_ID,"GID-MQ-FAQ"); Consumer consumer=ONSFactory.createConsumer(properties); consumer.subscribe("MQ-FAQ-TOPIC-1","NM-MQ-FAQ",new MessageListener(){ public Action consume(Message message,ConsumeContext context){ System.out.println("Receive: "+message); return Action.CommitMessage; } }); consumer.start();
JVM-2 上的代码示例如下:
Properties properties = new Properties(); properties.put(PropertyKeyConst.GROUP_ID,"GID-MQ-FAQ"); Consumer consumer=ONSFactory.createConsumer(properties); consumer.subscribe("MQ-FAQ-TOPIC-2","NM-MQ-FAQ",new MessageListener(){ public Action consume(Message message,ConsumeContext context){ System.out.println("Receive: "+message); return Action.CommitMessage; } }); consumer.start();
错误示例二:
同一 Group ID(GID-MQ-FAQ)订阅的 Topic 相同,但 Tag 不同(分别是 NM-MQ-FAQ-1、NM-MQ-FAQ-2)。
JVM-1 上的代码示例如下:
Properties properties =new Properties(); properties.put(PropertyKeyConst.GROUP_ID,"GID-MQ-FAQ"); Consumer consumer =ONSFactory.createConsumer(properties); consumer.subscribe("MQ-FAQ-TOPIC-1","NM-MQ-FAQ-1",new MessageListener(){ public Action consume(Message message,ConsumeContext context){ System.out.println("Receive: "+ message); return Action.CommitMessage; } }); consumer.start();
JVM-2 上的代码示例如下:
Properties properties =new Properties(); properties.put(PropertyKeyConst.GROUP_ID,"GID-MQ-FAQ"); Consumer consumer =ONSFactory.createConsumer(properties); consumer.subscribe("MQ-FAQ-TOPIC-1","NM-MQ-FAQ-2",new MessageListener(){ public Action consume(Message message,ConsumeContext context){ System.out.println("Receive: "+ message); return Action.CommitMessage; } }); consumer.start();
解决方案:
请确保在不同 JVM 中使用相同的 Group ID 启动多个 Consumer 时,配置的 Topic 和 Tag 是一致的。