RabbitMQ外部程序发送消息无法入队而控制台发布消息可以入队问题解析 内存阈值和磁盘阈值

RabbitMQ外部程序发送消息无法入队而控制台发布消息可以入队问题解析

在这里插入图片描述

问题描述

在使用RabbitMQ过程中发现消息都不入队了,程序把消息发过去队列接不到,而且有些时候生产者端没有异常反馈,但是在控制台publish消息的话消费者程序又能接收到,这个情况一般就是Rabbit服务开启了流控。

流控的表现就是该服务节点会blocked所有生产者传入的网络流量;直到内存使用量低于报警线。


因为RabbitMQ提供两种协议HTTP和AMQP。这个流量控制,只是对AMQP生效的。对HTPP协议发送的消息并不会进行流量控制。所以,rabbitmq使用的总内存会超过vm_memory_limit也就不奇怪了。

故障表现

此时你将会看到日志:

2020-10-22 15:12:38.662 [info] <0.352.0> vm_memory_high_watermark set. Memory used:107716608 allowed:53687091
2020-10-22 15:12:38.662 [warning] <0.350.0> memory resource limit alarm set on node 'rabbit@my-rabbit'.
**********************************************************
*** Publishers will be blocked until this alarm clears ***
**********************************************************
2020-10-22 15:12:38.665 [info] <0.354.0> Enabling free disk space monitoring
2020-10-22 15:12:38.665 [info] <0.354.0> Disk free limit set to 50MB

然后检查控制台:

在这里插入图片描述

这就是内存已经低于了警告线

结果是 Publishers will be blocked until this alarm clears

但是此时控制台publish的消息还能入队并且消费者也能收到消息。

磁盘剩余可用空间报警也会导致流控。

解决方案

vm_memory_high_watermark 触发流量控制的内存阈值,可以为相对值(0.5),或者绝对值
vm_memory_high_watermark.relative = 0.6

vm_memory_high_watermark.absolute = 2GB
默认vm_memory_high_watermark.relative = 0.4

阈值默认值0.4
默认值0.4表示安装的RAM或者可用虚拟地址空间两者较小的40%,如果在一个32位机器上,你安装了4G内存,4G的40%是1.6G,但是在32位Windows上,每个进程限制2G,所有阈值实际上是2G的40%(820M).

在最坏的情况下,Erlang的垃圾收集器会导致使用的内存数量增加一倍(默认情况下是80%的RAM)。强烈建议启用OS交换或page文件。

生产环境下建议内存阈值线不要设置超过49%

docker环境下指定内存阈值

docker的话推荐通过启动容器时指定
环境变量配置-e RABBITMQ_VM_MEMORY_HIGH_WATERMARK=0.95

指定为RabbitMQ可以使用95%的内存

$ docker run -d --hostname my-rabbit --name rabbitmq -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -e RABBITMQ_VM_MEMORY_HIGH_WATERMARK=0.95 -p 15672:15672 -p 5672:5672 -p 25672:25672 -p 61613:61613 -p 1883:1883 -m 128m rabbitmq:3.8.9-management

当然你也可以直接到配置文件修改配置/etc/rabbitmq/rabbitmq.conf

可以通过编辑配置来调整触发流控的内存阈值,下面是把阈值设置位默认值0.5

vm_memory_high_watermark.relative = 0.5

通过设置一个RAM绝对值来调整,下面的例子把阈值设置位1073741824字节(1024M)

vm_memory_high_watermark.absolute = 1073741824
相同的例子,但是使用内存单位

vm_memory_high_watermark.absolute = 1024MB

正常的情况:
在这里插入图片描述

禁用所有的发布

设置阈值为0,会立即触发内存警告,阻塞所有的发布连接(如果你希望禁用全局发布,这是非常有用的),使用rabbitmqctl set_vm_memory_high_watermark 0.

禁用内存流控

如果你想禁止基于内存的流量控制,你可以将该参数vm_memory_high_watermark 设置为100。

磁盘空间阈值

当可用磁盘空间下降到配置值(默认为50M)之下,一个警告会触发,所有的生产者会被阻塞,目标是避免填充整个磁盘,这会导致节点的写操作失败,导致Rabbit MQ中断,为了减小填充磁盘的风险,所有进来的消息都会阻塞,在内存的压力下,瞬时的消息,也会被page到磁盘,将继续占用已经到达临界值的磁盘空间,如果斯潘警告设置的太低,消息被快速page,有可能在两次磁盘空间检查之间填充完整个磁盘,导致Rabbit MQ崩溃(10s),一种更保守的方法是将限制设置为与系统上安装的内存量相同的限制(参见下面的配置)。

如果磁盘可用空间下降到配置值之下,警告会触发,broker数据库使用的磁盘或者分区的可用空间每10S就会检测一次,用来决定是否触发或者清楚警告,监控会从服务器一启动的时候就开始。

当在集群中运行Rabbit MQ的时候,磁盘警告也是集群范围的,如果一个节点达到限制值之下,所有的节点都会阻塞进来的消息。

Rabbit MQ会定时检查可用磁盘空间大小,这个频率跟上次检查时可用空间大小相关(以确保在磁盘将要耗尽时,磁盘警告能及时触发),一般是每10S检查一下磁盘空间,但是当接近限制值时,频率会提升,当非常接近的时候检测会1秒10此,它可能会影响系统的负载。

当可用磁盘空间下降到配置值之下,Rabbit MQ会阻塞生产者,阻止内存中的消息page到磁盘,这会减少磁盘被耗尽而导致崩溃的风险,但是不能完全杜绝。特别是消息被快速page到磁盘,有可能在两次磁盘检查之间用完整个可用空间,保守的做法如下:

配置磁盘可用空间值

磁盘可用空间limit是通过disk_free_limit设置的,默认的50M是为了数据库分区可用,配置文件设置可用空间为1GB。

disk_free_limit.absolute = 1000000000
加上单位(KB,MB,GB)

disk_free_limit.absolute = 1GB

带单位

也可以设置磁盘可用空间跟机器上的内存相关,这个配置设置磁盘可用跟内存大小一样

disk_free_limit.relative = 1.0

disk_free_limit Rabbitmq存储数据的可用空间限制,当低于该值的时候,将触发流量限制,设置可参考vm_memory_high_watermark参数 disk_free_limit.absolute = 50MB

disk_free_limit Rabbitmq存储数据的可用空间限制,当低于该值的时候,将触发流量限制,设置可参考vm_memory_high_watermark参数 disk_free_limit.absolute = 50MB

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值