我一直在阅读有关 AMQP 消息传递确认的原理。 (https://www.rabbitmq.com/confirms.html)。确实很有帮助且写得很好的文章,但有关消费者致谢的一个特别的事情确实令人困惑,以下是引用:
使用自动确认模式时需要考虑的另一件事是消费者超载.
消费者超载?消息队列由代理处理并保存在 RAM 中(如果我理解正确的话)。这是关于什么过载?消费者是否有某种第二队列?
该文章的另一部分更令人困惑:
因此,消费者可能会对送货速度感到不知所措,在内存中积累积压并耗尽堆或让操作系统终止其进程。
什么积压?这一切是如何协同工作的?消费者完成哪部分工作(当然除了消费消息和处理消息)?我认为代理正在保持队列活动并转发消息,但现在我正在阅读一些神秘的积压和消费者过载。这真的很令人困惑,有人可以解释一下或者至少指出我的好来源吗?
我相信您所指的文档处理了我认为 AMQP 0-9-1 或 RabbitMQ 的实现中的设计缺陷。
考虑以下场景:
- 队列中有数千条消息
- 单个消费者订阅队列
AutoAck=true
并且没有设置预取计数
将会发生什么?
RabbitMQ 的实现是向没有预取计数的客户端传递任意数量的消息。此外,对于自动确认,预取计数是无关紧要的,因为消息在传递给消费者时得到确认。
内存缓冲区:消费者的默认客户端 API 实现有一个内存缓冲区(在 .NET 中,它是某种类型的阻塞集合(如果我没记错的话))。因此,在处理消息之前,但在从代理接收到消息之后,它进入这个内存中的保存区域。现在,设计缺陷就是这个保存区域。消费者别无选择,只能接受来自代理的消息,因为它是异步发布到客户端的。这是AMQP协议规范(参见第 53 页)。
因此,此时队列中的每条消息都将立即传递给消费者,并且消费者将被消息淹没。假设每条消息都很小,但需要 5 分钟来处理,那么这个消费者完全有可能在任何其他消费者附加到它之前耗尽整个队列。自从AutoAck
打开后,代理将在传递后立即忘记这些消息。
显然,如果您想要处理这些消息,这不是一个好的场景,因为它们已经离开了代理的相对安全性,并且现在位于消费端点的 RAM 中。假设遇到了导致消费端点崩溃的异常 - 噗,所有消息都消失了。
如何解决这个问题?
您必须关闭 Auto-Ack,通常设置合理的预取计数也是一个好主意(通常 2-3 就足够了)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)