内存和磁盘警告
有两种情况下,Rabbit MQ会停止读取客户端的连接socket,为了防止crash崩溃,这两种情况是:
内存使用达到配置值
磁盘空间下降到配置值下
在这两种情况下,服务器会临时阻塞连接—服务器会暂停读取发布消息的客户端的连接,连接心跳监控也会被禁用,在rabbitmqctl和管理查建中的所有网络连接如果是blocking状态,意味着他们没有尝试发送,因此可以继续,如果是blocked状态,意味着他们已经发布了,现在需要被暂停。
集群的警告
当运行Rabbit MQ集群的时候,内存和磁盘警告是集群范围的,如果一个节点达到了限制,所有的节点都会阻塞连接。
这样的意图是停止生产者,但是让消费者继续不受影响,但是因为协议允许生产者和消费者在同一个Channel或者同一个连接的不同Channel上进行操作,这个逻辑是不完美的,在实践中,不会产生任何问题,因为节流作为一种延迟被观察,尽管如此,建议使用单独的连接分别作为生产和消费。
文件描述符耗尽 Running out of File Descriptors
当服务器使用了操作系统分配给它的所有文件描述符,它会拒绝客户端连接,参考 “网络指南” 学习更多。
当客户端尝试发送比服务器接收消息快的时候,它们会进入瞬时的流控。
相关主题
内存如何限制工作
磁盘如何限制工作
客户端可以检测它们是否被阻塞
内存警告
Rabbit MQ服务器在启动和执行 rabbitmqctl set_vm_memory_high_watermarkfraction的时候会检测机器上的RAM大小,默认情况下,Rabbit MQ使用内存超过40%的时候,会发出内存警告,阻塞所有发布消息的连接,一旦警告解除(etc,服务器paging消息到硬盘或者分发消息到消费者并且确认)服务会恢复正常。
默认的内存阈值是40%,注意,这并不会阻止Rabbit MQ Server使用不到40%,仅仅意味着到达这个点的时候,发布者会被扼杀,最坏的情况下,Erlang虚拟机会引起双倍的内存使用(RAM的80%),强烈建议开启操作系统的SWAP和Page Files。
32位架构每个进程的内存限制是2G,一般的64位(AMD或者Interleaving)每个进程允许256T,64位的Windows限制位8T,但是,即使在64位下,32的进程最大可用地址空间也是2G。
配置内存阈值
可以通过编辑配置文件来调整触发流控的内存阈值,下面是把阈值设置位默认值0.4
vm_memory_high_watermark.relative = 0.4
下面是使用经典配置格式:
[{rabbit, [{vm_memory_high_watermark, 0.4}]}].
默认值0.4表示安装的RAM或者可用虚拟地址空间两者较小的40%,如果在一个32位机器上,你安装了4G内存,4G的40%是1.6G,但是在32位Windows上,每个进程限制2G,所有阈值实际上是2G的40%(820M).
另外,内存阈值可以通过设置一个RAM绝对值来调整,下面的例子把阈值设置位1073741824字节(1024M)
vm_memory_high_watermark.absolute = 1073741824
相同的例子,但是使用内存单位
vm_memory_high_watermark.absolute = 1024MB
使用经典配置格式
[{rabbit, [{vm_memory_high_watermark, {absolute, 1073741824}}]}].
经典格式带单位
[{rabbit, [{vm_memory_high_watermark, {absolute, "1024MiB"}}]}].
如果这个绝对值比安装的RAM或者可用虚拟地址空间大,阈值会被设置位较小的。
内存限制在Rabbit MQ Server启动的时候,会被附加到RABBITMQ_NODEHOME.log日志上。
=INFO REPORT==== 29-Oct-2009::15:43:27 ===
Memory limit set to 2048MB.
在borker运行的时候也可以使用 rabbitmqctl set_vm_memory_high_watermark fraction 命令或者 rabbitmqctl set_vm_memory_high_absolute memory_limit命令,内存单位也可以使用,命令会立即生效,直到broker停止,如果broker重新启动也要生效的话,相应的配置文件也要改变,在执行此命令但是不改变阈值的情况下,在具有热交换的RAM系统里面,阈值可能会变化(因为内存总量变了。。)
禁用所有的发布
设置阈值为0,会立即触发内存警告,阻塞所有的发布连接(如果你希望禁用全局发布,这是非常有用的),使用rabbitmqctl set_vm_memory_high_watermark 0.
有限的地址空间
当在64位机器上运行32位Erlang,地址内存是受限制的,服务器会检测并打印如下一条消息:
=WARNING REPORT==== 19-Dec-2013::11:27:13 ===
Only 2048MB of 12037MB memory usable due to limited address space.
Crashes due to memory exhaustion are possible - see
http://www.rabbitmq.com/memory.html#address-space
内存警告不是完美的,尽管停止发布通常会阻止内存的进一步使用,但还是有相当大的可能,其它一些东西会继续提升内存的使用,通常,这种情况发生的时候,物理内存被耗尽,操作系统会开始交换,但是使用一个受限的地址空间,当超过这个限制的时候,会引起VM的帮亏。
因此强烈建议,在64位OS上运行64位Erlang虚拟机。
配置Paging阈值
在broker达到high watermark阻塞发布者之前,它会尝试通过将队列的内容page到磁盘来释放内存,持久化和瞬时消息都会被page out.
默认情况下,在borker达到阈值的50%时(默认内存阈值是0.4,当0.2的内存被使用时)会发生这种情况。可以通过修改 vm_memory_high_watermark_paging_ration配置来进行修改:
vm_memory_high_watermark_paging_ratio = 0.75
vm_memory_high_watermark.relative = 0.4
使用经典配置:
[{rabbit, [{vm_memory_high_watermark_paging_ratio, 0.75},
{vm_memory_high_watermark, 0.4}]}].
上面的配置会在内存使用到04.*0.75=0.3的时候开始paging,在内存使用到0.4的时候阻塞发布者。可以把vm_memory_high_watermark_paging_ratio设置的比1大,在这种情况下,队列不会把内容page到磁盘,如果引起了内存警告,生产者会跟上面解释的一样被阻塞。
不识别的平台
如果Rabbit MQ Server不能识别你的系统,它会在RABBITMQ_NODENAME.log文件中追加一条信息,接着它会假设有1GRAM安装。
=WARNING REPORT==== 29-Oct-2009::17:23:44 ===
Unknown total memory size for your OS {unix,magic_homegrown_os}. Assuming memory size is 1024MB
在这种情况下,vm_memory_high_watermark配置值会使用1G,在使用默认值0.4的时候,RabbitMQ的内存阈值是410M,因此当内存使用超过410M的时候,它就会扼杀生产者,当Rabbit MQ不识别你的平台的时候,如果你有8GRAM,你希望阈值设置位0.3在内存超过3G的时候来throttle生产者,
磁盘警告
当可用磁盘空间下降到配置值(默认为50M)之下,一个警告会触发,所有的生产者会被阻塞,目标是避免填充整个磁盘,这会导致节点的写操作失败,导致Rabbit MQ中断,为了减小填充磁盘的风险,所有进来的消息都会阻塞,在内存的压力下,瞬时的消息,也会被page到磁盘,将继续占用已经到达临界值的磁盘空间,如果斯潘警告设置的太低,消息被快速page,有可能在两次磁盘空间检查之间填充完整个磁盘,导致Rabbit MQ崩溃(10s),一种更保守的方法是将限制设置为与系统上安装的内存量相同的限制(参见下面的配置)。
如果磁盘可用空间下降到配置值之下,警告会触发,broker数据库使用的磁盘或者分区的可用空间每10S就会检测一次,用来决定是否触发或者清楚警告,监控会从服务器一启动的时候就开始,在log file中会增加一条条目:
=INFO REPORT==== 23-Jun-2012::14:52:41 ===
Disk free limit set to 953MB
在不识别的平台上,监控会禁用,日志中打印消息:
=WARNING REPORT==== 23-Jun-2012::15:45:29 ===
Disabling disk free space monitoring
当在集群中运行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
使用经典的格式
[{rabbit, [{disk_free_limit, 1000000000}]}].
带单位
也可以设置磁盘可用空间跟机器上的内存相关,这个配置设置磁盘可用跟内存大小一样
disk_free_limit.relative = 1.0
经典配置
[{rabbit, [{disk_free_limit, {mem_relative, 1.0}}]}].
这个配置可以在broker运行的时候通过命令rabbitmqctl set_disk_free_limit 大小
或者rabbitmq_disk_free_limit mem_relative 值来使用,这个命令会立即生效,直到broker停止,如果重启也要生效的话,需要修改配置文件。
流控
RabbitMQ会降低连接的速度,当发送太快队列跟不上的时候,不需要进行配置。
一个流控的连接在rabbitmqctl和管理插件中会显示flow状态,这意味着这个连接每一秒会被阻塞,接触阻塞好几次,使消息的接收速率能匹配上服务器处理的速率。
一般来说,受流控的连接跟正常运行的是没什么不同的,流控状态来通知sysadmin,发送速率应该受限,但是从客户端的角度,它看起来只是服务器的带宽比实际低而已。
欢迎工作一到五年的Java工程师朋友们加入Java架构开发: 855835163
群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!