解决RabbitMQ队列超长QueueingCons…

本文讲述了在使用RabbitMQ时遇到队列超长,导致服务器内存占用过高的情况。通过jstat和jmap分析,发现是由于QueueingConsumer持有大量对象引发的内存溢出。解决方案是调用Channel的basicQos方法,限制临时内存中保存的消息数,以避免类似问题的发生。合理设置QoS参数是避免RabbitMQ队列雪崩的关键。

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

      我们的服务器使用RabbitMQ作为消息中转的容器。某天我怀疑RabbitMQ队列 是否都能及时消化。于是用命令查询了下:rabbitmqctl list_vhosts | grep -P ".*\.host" | xargs -i rabbitmqctl list_queues -p {} | grep "queue"。   不查不知道,一查吓一跳:大多数服务器的队列基本上都是空的,但是有些服务器的某个队列竟然有超过500W条的记录。一般 RabbitMQ进程占用内存不过100M-200M,这些队列超长的 RabbitMQ 进程可以占用超过2G的内存。
        显然消息队列的消费者出现了问题。开发查看日志发现作为该队列消费者的Java服务的日志也卡住了,重启服务 (这点做得不对,应该用jstat、jstack进行排查,而不是直接重启)又很快卡住。这时候他才想起来用jstat,通过jstat发现JVM内存都耗尽了,之后进入无尽的Full GC,所以当然不会处理队列消息和输出日志信息了。jstat的输出如下:
------------------------------------- -------------------------------------
[root@mail ~]# jstat -gcutil 29389
  S0     S1     E       O       P     YGC     YGCT     FGC     FGCT     GCT    
100.00   0.00 100.00 100.00   59.59   1639     2.963 219078 99272.246 99275.209
------------------------------------- -------------------------------------
       使用jmap导出这时候的Java堆栈,命令:jmap -dump:format=b,file= 29389.hprof   29389。将得到的dump文件放到MAT( Eclipse Memory Analyzer) 里进行分析,发现很明显是QueueingConsumer持有大量对象导致JVM内存溢出,截图如下:
        解决RabbitMQ队列超长QueueingConsumer导致JVM内存溢出的问题
      上网搜索了下,发现有人遇到了类似的问题: RabbitMQ QueueingConsumer possible memory leak  。解决办法是调用Channel的basicQos方法,设置临时内存中最多保存的消息数。这个数值的设置建议参考  《Some queuing theory: throughput, latency and bandwidth》  权衡决定。
      拍脑袋将 basicQos设置为16后重启服务,队列终于开始消化了。用jstat 观察JVM内存使用情况,也没有再出现剧增溢出的现象。
      总结:使用RabbitMQ的时候,一定要合理地设置QoS参数。 我感觉RabbitMQ的默认做法其实是很脆弱的,容易导致 雪崩。“You have a queue in Rabbit. You have some clients consuming from that queue. If you don't set a QoS setting at all (basic.qos), then Rabbit will push all the queue's messages to the clients as fast as the network and the clients will allow.“。 这样如果由于某些原因,队列中堆积了比较多的消息,就可能导致Comsumer内存溢出卡死,于是发生 恶性循环,队列消息不断堆积得不到消化, 彻底地悲剧了。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值