Activemq与HttpClient套接字读取超时:消费者停止消费问题排查
兄弟,针对你遇到的这个消费者突然停掉、Broker还没报错的问题,结合你给出的ServiceMix 5.6.0 + AMQ 5.12.3环境,我分享几个实际排查过的思路,应该能帮到你:
排查消费者停滞的核心步骤
1. 先扒Broker的真实状态(别光看报错日志)
- 登Broker2的管理控制台(默认是
http://<broker2-ip>:8161/admin),重点查这几个地方:- Queues面板:看对应队列的
Messages Enqueued/Messages Dequeued还在涨吗?Consumers数量是不是显示有但没消费动作?Messages In Flight有没有一直挂着的消息(这种就是被消费者锁住没确认的) - Connections面板:客户端的连接是不是还活着?有没有长时间Idle但没断开的连接?
- Topics面板(如果用的是主题):订阅者状态正常吗?有没有未确认的持久化订阅消息?
- Queues面板:看对应队列的
- 既然已经开了全堆栈日志,重点搜这些关键词:
JMSException、ConnectionFactory相关的异常(哪怕是WARN级别的也要注意)ThreadPool、TaskExecutor的阻塞日志(AMQ 5.12.x偶尔会出现线程池耗尽,导致消费线程拿不到资源)Consumer的stop()、shutdown()调用记录(说不定是某个地方主动停了消费者)
2. 客户端侧的消费逻辑是重灾区
- 如果你用Camel路由消费,先查Camel状态:
- 在ServiceMix控制台敲
camel:context-list,看对应路由是不是Started状态,有没有莫名变成Suspended或者Stopped - 看Camel的日志,找
ConsumerTemplate、PollingConsumer的异常,比如是不是出现了事务未提交或者消息确认超时?毕竟Spring 3.2.x的事务管理器和AMQ配合偶尔会有小坑
- 在ServiceMix控制台敲
- 测试客户端也要自查:是不是用了无超时的
receive()方法?比如:
哪怕队列有消息,要是消息被锁住了也消费不了,这时候看队列的Message message = consumer.receive(); // 没设置超时的话,没消息就会一直阻塞Messages In Flight就能确认
3. 网络和依赖兼容性别忽略
- Broker1和Broker2之间的网络:有没有间歇性丢包?可以在Broker2的
activemq.xml里开transport的调试日志,抓同步消息时的异常:<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?transport.commandTracingEnabled=true&transport.trace=true"/> - 依赖版本冲突要警惕:你用的HttpClient 4.5.1、HttpCore 4.4.4,而AMQ 5.12.x本身依赖的是HttpClient 4.3.x,版本差得有点多,很可能出现连接池或者HTTP调用异常,进而卡消费线程。在ServiceMix里敲
osgi:headers org.apache.activemq.activemq-core,看看AMQ依赖的HttpClient版本,对比你的项目里的版本是否一致
4. 少量消息也可能出问题
- 检查有没有大消息或者格式异常的消息:比如消息体特别大,消费者解析时OOM或者无限循环;或者消息格式不符合预期,导致消费线程卡住。可以尝试从队列里取出可疑消息,用测试客户端单独消费试试
- 持久化层排查:AMQ 5.12默认用KahaDB,看看
data/kahadb目录下的db.log有没有CorruptJournal相关的日志,要是KahaDB损坏,也会导致消息读不出来
5. 线程和资源耗尽排查
- 在ServiceMix里敲
shell:threads,看JVM线程状态:重点找BLOCKED或者WAITING状态的线程,尤其是AMQ、Camel相关的线程,说不定是某个线程锁死了 - 查JVM内存:用
jmap或者jconsole看堆内存/非堆内存使用情况,要是内存泄漏导致GC频繁,也会阻塞消费线程
内容的提问来源于stack exchange,提问作者Rajesh
相关产品推荐
相关产品推荐

