前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为何RabbitMQ的队列不能接收生产者发送过来的消息

为何RabbitMQ的队列不能接收生产者发送过来的消息

作者头像
灰子学技术
发布2021-02-05 11:00:51
1.3K0
发布2021-02-05 11:00:51
举报
文章被收录于专栏:灰子学技术

本文章主要介绍RabbitMQ的队列不能接收生产者发送过来的消息的几种场景:

代码语言:javascript
复制
1.rabbitmq上面堆积的没有ack的消息太多,导致超过了max-length的限制
2.rabbitmq上面的内存超过了限制,触发了流量控制
3.rabbitmq上面触发了太多的I/O磁盘操作,导致rabbitmq不能及时响应

场景 1: rabbitmq上面的消息堆积太多

对于rabbitmq的queue来说,是可以设置下面三个参数的,x-max-length,x-max-length-bytes, x-overflow。一旦x-max-length(这里是设置的queue最大容纳的消息数量),x-max-length-bytes(这里是queue中的消息数量与消息大小乘积的总量)超过了限制之后,就会根据x-overflow里面设置的模式开始处理,对于x-overflow有一个reject-publish模式,打开之后,生产者通过confrim生产的消息,在rabbitmq就会被拒绝,回复message unacked.

这几个参数的解释说明:

备注:这几个参数是可选的,默认不会被设置,默认值的话,这几个值是取决于rabbitmq这个机器的cpu,内存等的配置。

详情可以参考官方文档:https://www.rabbitmq.com/maxlength.html

例子

场景2: rabbitmq上面的内存超过了限制,触发流量控制,导致的失败

这个对应的是另外两个参数,vm_memory_high_watermark 和vm_memory_limit与流量控制相关的内存参数。

RabbitMQ会在启动和执行命令rabbitmqctl set_vm_memory_high_watermark 百分比的时候检测系统所安装的内存总量。默认情况,当RabbitMQ服务器使用超过40%的内存时,它会引起一个内存报警并且阻塞所有连接。一旦内存报警清除后(例如,由于RabbitMQ服务器将消息页交换到磁盘或者分发到客户端时)就会恢复正常服务了。

触发了这个内存超限之后,rabbitmq就会启动流量控制,对于流量控制,下面是三种不同的设置方法:

(参考文档:https://www.rabbitmq.com/memory.html)

代码语言:javascript
复制
1.如果你在引起内存报警的时候尝试发送消息,在进行发送期间就会被阻塞了。
2.如果你想阻塞所有的发送者,你可以将该参数 vm_memory_high_watermark 设置为0。
3.如果你想禁止基于内存的流量控制,你可以将该参数vm_memory_high_watermark 设置为100。

流量控制介绍:

当达到内存阀值的时候(无论设置的是百分比,还是绝对值),RabbitMQ就会触发流量控制。即publishers会全部阻塞,直到解除报警才会恢复正常的publishers服务。触发了的流量控制之后,在rabbitmq的UI界面,可以看下面的这个指标:

备注:这个流量控制,只是对AMQP生效的,对HTPP协议发送的消息并不会进行流量控制。

对于流量控制的详细介绍可参考下面两篇文章:

代码语言:javascript
复制
1.https://www.rabbitmq.com/blog/2015/10/06/new-credit-flow-settings-on-rabbitmq-3-5-5/
2.https://www.rabbitmq.com/blog/2014/04/14/finding-bottlenecks-with-rabbitmq-3-3/

场景3: rabbitmq上面触发了太多的I/O磁盘操作,导致rabbitmq不能及时响应

这个场景实际上有两种情况:1、一种是publisher采用confrim机制的时候,设置了mode为永久化(persistent)。

这种场景的时候,publisher接收到rabbitmq的ack必须是在rabbitmq写完硬盘之后,才将ack消息返回。一旦rabbitmq上面写硬盘的速度太慢,就会导致ack的返回超时,进而会导致publisher发送message到rabbitmq批量失败。

这种问题的定位办法比较简单,登录到rabbitmq的那台机器上面,查看对应的磁盘I/O的读写情况就可以了,一旦超过限制,跟它的关系就很大。

而针对这个场景的解决办法,其实没有太多办法,一个是增加磁盘的读写速度,换更高级的磁盘,一个是想办法把生产的消息从业务层面来减少消息生产速度。

2.另一种场景是rabbitmq上面堆积的消息过多,而queue的设置里面恰好设置了durable设置为true,也就是持久化队列到磁盘。

在rabbitmq上面的消息堆积过多的时候,内存不足的时候就会引起消息换出到磁盘,而频繁的写磁盘,会导致rabbitmq的服务变得很慢,进而会影响publisher的ack响应。

解决办法通常是下面三种:

代码语言:javascript
复制
1.进行流量控制。
2.增加prefetch的值,即一次发送多个消息给接收者,加快消息被消费掉的速度。
2.采用multiple ack,降低处理ack带来的开销。

参考资料:https://blog.csdn.net/u013256816/article/details/71097186


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 灰子学技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 这个对应的是另外两个参数,vm_memory_high_watermark 和vm_memory_limit与流量控制相关的内存参数。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档