RabbitMQ问题汇总

本文介绍了RabbitMQ的日志插件启用、日志级别和路径设置,以及如何处理网络分区和节点容量配置。通过调整`vm_memory_high_watermark`参数,可以控制内存使用以避免消息写入受影响。同时,设置了磁盘自由空间限制以确保消息持久化。当遇到队列超长导致JVM内存溢出问题时,通过调整`basicQos`参数限制内存中待处理消息数量,避免消费者内存溢出。
摘要由CSDN通过智能技术生成

日志插件

开启日志记录插件(可通过管理界面查看)

rabbitmq-pluginsenablerabbitmq_tracing

rabbitmqctltrace_on

打开trace会影响消息写入功能,适当打开后请关闭。

安装上面的插件并开启trace_on之后,会发现多了两个exchange:amq.rabbitmq.trace和amq.rabbitmq.log,类型均为:topic。

只要订阅这两个主题,就能收到:客户端连接、消息发收等具体信息了。

设置rabbitmq日志级别和路径

vi/etc/rabbitmq/rabbitmq.conf

[

{rabbit,[{log_levels,[{connection,warning}]}]}

].

也可以这样写成

[

{rabbit,[{log_levels,[{connection,error}]}]}

].

ps:最后的]有.号的,希望不要忽略了.

日志文件路径设置

vi/etc/rabbitmq/rabbitmq-env.conf

RABBITMQ_LOG_BASE=/vol/pic/log/rabbitmq

ps:默认路径/var/log/rabbitmq

网络分区恢复

http://www.rabbitmq.com/partitions.html

/etc/rabbitmq.config

[

{rabbit,

[{tcp_listeners,[5672]},

{cluster_partition_handling,ignore}]

}

].

rabbitmq节点容量配置

http://www.rabbitmq.com/memory.html

rabbitmqctlset_vm_memory_high_watermark0.5//将rabbitmq占用机器的内存上限改为0.5

可以通过

rabbitmqctlstatus查看结果中的  {vm_memory_high_watermark,0.5}

===

内存管理

RabbitMQ服务器在启动时会计算系统内存总大小。然后会根据vm_memory_high_watermark参数指定的百分比,进行控制.可通过命令rabbitmqctlset_vm_memory_high_watermarkfraction动态设置。

默认下,vm_memory_high_watermark的值为0.4,当RabbitMQ使用的内存超过40%时,系统会阻塞所有连接。一旦警报解除(消息被消费者取走,或者消息被写到硬盘中),系统重新恢复工作。

32位系统的单进程内存使用最大为2G,即使系统有10G,那么内存警报线为2G*40%.

在日志中可以找到内存限制的相关信息

例如:/home/data/rabbitmq/log

=INFOREPORT==28-Apr-2015::14:11:16=

Memorylimitsetto3804MBof7609MBtotal.

当vm_memory_high_watermark为0时,不再有内存警报。并且所有的消息发布都将停止。这个方法可用来,如果要禁止消息发布的情况。


磁盘管理

在日志中可以找到内存限制的相关信息

例如:/home/data/rabbitmq/log

=INFOREPORT==28-Apr-2015::14:11:16=

Diskfreelimitsetto50MB

当RabbitMQ内存使用达到预设值,并且阻塞信息发布前,会尝试把内存中的信息输出到磁盘上。持久化信息和非持久化信息都将被写到磁盘。(持久化信息一进入队列就会被写到磁盘)

如果磁盘的预设值为50%,内存预设值默认是0.4,那么就是当内存使用量达到20%时,队列信息会被写到磁盘上。

可以通过设置vm_memory_high_watermark_paging_ratio(默认值为0.5)来改变写入磁盘的策略,例如:

[{rabbit,[{vm_memory_high_watermark_paging_ratio,0.75},{vm_memory_high_watermark,0.4}]}].

Theaboveconfigurationstartspagingat30%ofmemoryused,andblockspublishersat40%.

上面的配置将会在内存全用30%时将队列信息写入到磁盘,阻塞信息发布是在内存使用40%时发生。

建议vm_memory_high_watermark不超过50%.

RabbitMQ队列超长导致QueueingConsumerJVM溢出

解决RabbitMQ队列超长QueueingConsumer导致JVM内存溢出的问题

我们的服务器使用RabbitMQ作为消息中转的容器。某天我怀疑RabbitMQ队列是否都能及时消化。于是用命令查询了下:rabbitmqctllist_vhosts|grep-P".*.host"|xargs-irabbitmqctllist_queues-p{}|grep"queue"。不查不知道,一查吓一跳:大多数服务器的队列基本上都是空的,但是有些服务器的某个队列竟然有超过500W条的记录。一般RabbitMQ进程占用内存不过100M-200M,这些队列超长的RabbitMQ进程可以占用超过2G的内存。

显然消息队列的消费者出现了问题。开发查看日志发现作为该队列消费者的Java服务的日志也卡住了,重启服务后(这点做得不对,应该用jstat、jstack进行排查,而不是直接重启)又很快卡住。这时候他才想起来用jstat,通过jstat发现JVM内存都耗尽了,之后进入无尽的FullGC,所以当然不会处理队列消息和输出日志信息了。jstat的输出如下:

--------------------------------------------------------------------------

[root@mail~]#jstat-gcutil29389

S0S1EOPYGCYGCTFGCFGCTGCT

100.000.00100.00100.0059.5916392.96321907899272.24699275.209

--------------------------------------------------------------------------

使用jmap导出这时候的Java堆栈,命令:jmap-dump:format=b,file=29389.hprof29389。将得到的dump文件放到MAT(EclipseMemoryAnalyzer)里进行分析,发现很明显是QueueingConsumer持有大量对象导致JVM内存溢出,截图如下:

上网搜索了下,发现有人遇到了类似的问题:RabbitMQ?QueueingConsumer?possible?memory?leak。解决办法是调用Channel的basicQos方法,设置临时内存中最多保存的消息数。这个数值的设置建议参考《Some?queuing?theory:?throughput,?latency?and?bandwidth》权衡决定。

拍脑袋将basicQos设置为16后重启服务,队列终于开始消化了。用jstat观察JVM内存使用情况,也没有再出现剧增溢出的现象。

总结:使用RabbitMQ的时候,一定要合理地设置QoS参数。我感觉RabbitMQ的默认做法其实是很脆弱的,容易导致雪崩。“YouhaveaqueueinRabbit.Youhavesomeclientsconsumingfromthatqueue.Ifyoudon’tsetaQoSsettingatall(basic.qos),thenRabbitwillpushallthequeue’smessagestotheclientsasfastasthenetworkandtheclientswillallow.“。这样如果由于某些原因,队列中堆积了比较多的消息,就可能导致Comsumer内存溢出卡死,于是发生恶性循环,队列消息不断堆积得不到消化,彻底地悲剧了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值