RocketMq消息不消费,线程阻塞

本文记录了一次 RocketMQ 消息消费故障的排查过程,包括查看MQ看板、服务日志和进程信息。发现服务因HTTP请求无超时设置导致线程阻塞,修复此问题后,设置HTTP请求超时避免线程长时间等待,从而解决了消息不消费的积压问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、背景

遇到一个现场问题,多个地区(多地独立部署)在某个时间节点之后rocketmq的消息都不消费了,重启服务之后会消费一部分,过不了多久又会不消费

二、排查过程

2.1查看mq看板

  • 看具体的某个消息,都是not_consumer,点击重新发送,可以被正常消费;但是服务不会自动消费
  • 未消费的消息进入重试队列,并堆积

2.2查看服务日志

重启之后看日志,从开始消费到不消费,有消费的过程中异常的;捕获异常并不再抛出,重新部署后不再有异常,但是还是会出现不消费的情况

2.3排查结论

从2.1可以看到消息手动是可以消费的,但是不会自动消费了,2.2看服务日志,没有明显报错,那还有什么情况下会出现消息不消费的情况呢?

  • 百度:没有得到有价值的问题
  • mq的配置问题会不会是有消息消费失败之后就不会继续消费了:从解决异常之后还是会出现这个问题来看并不是配置问题
    问题陷入困境,向上求助,提示看服务进程信息

三、dump进程信息分析

3.1dump进程信息

使用命令jps查看进程号,使用 jstack 进程号 >text.txt把进程信息保存到本地

3.2看进程信息

我使用的是在线的 https://fastthread.io/ 分析工具

其他还有TDA工具,https://github.com/irockel/tda/releases/tag/2.4

上传线程信息到 该网站
看火焰图
在这里插入图片描述
我的思路是先看自己的代码;所以找有自己的代码的线程栈信息
最高的这个线程是自己写的代码的,发现有4个线程在运行,并且是mq的消费者
在这里插入图片描述
里面有个doPost请求,会不会是这个请求的问题呢?
先访问这个地址,发现访问不了,按理说访问不了应该会超时抛出异常,但是并没有报错,导致线程一直在等待

四、问题解决

给doPost方法加上超时时间,超过30s就抛出异常,这样mq就不会一直等着了;重启后可以好一会儿是因为没有这个消费者的消息;为什么以前没问题,因为这个地址之前一直可以正常访问,最近由于网络不稳定会出现问题

  • http请求要加超时时间,不然会导致线程一直等待
  • 如果有个消息没有消费完,mq会一直阻塞等待,导致消息积压
### RocketMQ 消费消费的原因分析与解决方案 #### 1. 消费线程池配置合理 如果消费者的线程池配置过小,可能会导致消息积压,进而使得消费者看起来像是停止了工作。可以通过调整 `consumeThreadMin` 和 `consumeThreadMax` 参数来增加或减少消费线程的数量。 ```properties # 设置最小和最大消费线程数 consumeThreadMin=20 consumeThreadMax=40 ``` 对于高并发场景下,适当提高这两个参数有助于提升消费能力[^1]。 #### 2. 消息处理逻辑耗时较长 当单条消息的处理时间超过一定阈值(默认为15秒),RocketMQ 认为此消息处理超时并将其重新入队等待其他实例继续尝试处理。这可能导致大量未完成的任务堆积在当前节点上而无法及时得到响应。因此建议优化业务代码中的性能瓶颈部分,缩短每条记录的实际执行周期;或者通过设置合理的 `maxReconsumeTimes` 来控制重试次数,防止无限循环重试影响整体效率。 ```java // 配置最大允许的消息重试次数 consumer.setMaxReconsumeTimes(3); ``` 另外还可以考虑开启批量拉取模式(`pullBatch`)以减少频繁请求带来的开销,在一定程度上缓解此类情况的发生概率。 #### 3. Offset 提交机制失效 Offset 是指消费者读取消息的位置标记。一旦提交过程出现问题,则即使完成了正常的数据解析也无法更新最新的进度位置,从而造成后续新到来的信息始终处于待确认状态而被真正接收下来。具体表现为程序运行期间没有任何明显的错误提示但却迟迟见新的输出结果产生。此时应该重点排查以下几个方面: - **网络连接稳定**:确保客户端能够稳定地访问Broker集群; - **ACK反馈丢失**:检查是否有足够的内存资源供应用程序使用,避免因为OOM等原因而导致的心跳包发送失败; - **事务型操作当**:如果是分布式环境下涉及到多库同步等问题,则需特别注意跨平台间的一致性和原子性保障措施是否到位。 针对以上情形可采取如下改进策略: - 使用异步方式提交偏移量,降低主线程阻塞风险; - 定期手动触发commit动作而是依赖于自动机制; - 对每次成功的消费行为都附加唯一标识符用于追踪定位异常点所在。 ```java DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(); consumer.registerMessageListener((List<MessageExt> msgs, ConsumeConcurrentlyContext context) -> { try { // 处理消息... // 手动提交offset consumer.updateConsumeOffset(msgs.get(0), System.currentTimeMillis()); return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } catch (Throwable t) { logger.error("Failed to process message", t); return ConsumeConcurrentlyStatus.RECONSUME_LATER; } }); ``` #### 4. 序列化/反序列化兼容性问题 由于版本迭代或者其他因素的影响,生产端与消费端之间可能存在对象结构上的差异,最终引发诸如 `InvalidClassException` 类似的异常状况阻止进一步的操作流程。遇到这种情况应当仔细对比双方使用的类定义文件是否存在出入,并且保持二者之间的协调一致。必要时可通过引入自定义序列化框架如Protobuf 或 JSON 来规避传统 Java 序列化的局限性[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值