RabbitMQ 消费者过载

Siv*_*ich 5 producer-consumer amqp rabbitmq rabbitmq-exchange

我一直在阅读有关 AMQP 消息传递确认的原理。(https://www.rabbitmq.com/confirms.html)。文章确实很有帮助,写得很好,但有关消费者认知的一件事确实令人困惑,以下是引用:

使用自动确认模式时需要考虑的另一件事是消费者过载

消费者超载?消息队列由代理处理并保存在 RAM 中(如果我理解正确的话)。这是关于什么过载?消费者是否有某种第二队列?该文章的另一部分更令人困惑:

因此,消费者可能会因交付速度而不知所措,可能会在内存中积累积压并耗尽堆或让操作系统终止其进程。

什么积压?这一切是如何协同工作的?消费者完成哪部分工作(当然除了消费消息和处理消息)?我认为代理正在保持队列活动并转发消息,但现在我正在阅读一些神秘的积压和消费者过载。这真的很令人困惑,有人可以解释一下或者至少指出我的好来源吗?

the*_*yer 7

我相信您所指的文档处理了我认为 AMQP 0-9-1 或 RabbitMQ 的实现中的设计缺陷。

考虑以下场景:

  • 队列中有数千条消息
  • 单个消费者在设置AutoAck=true或未设置预取计数的情况下订阅队列

将会发生什么?

RabbitMQ 的实现是向没有预取计数的客户端传递任意数量的消息。此外,对于自动确认,预取计数是无关紧要的,因为消息在传递给消费者时得到确认。

内存缓冲区: 消费者的默认客户端 API 实现有一个内存缓冲区(在 .NET 中,它是某种类型的阻塞集合(如果我没记错的话)。因此,在消息处理之前,但在消息处理之后从broker接收到的消息,会进入这个内存中的保存区域。现在,设计缺陷就是这个保存区域。消费者别无选择,只能接受来自broker的消息,因为它是异步发布到客户端的。这个是AMQP 协议规范的一个缺陷(请参见第 53 页)。

因此,此时队列中的每条消息都将立即传递给消费者,并且消费者将被消息淹没。假设每条消息都很小,但需要 5 分钟来处理,那么这个消费者完全有可能在任何其他消费者附加到它之前耗尽整个队列。并且由于AutoAck打开了,经纪人会在发送后立即忘记这些消息。

显然,如果您想要处理这些消息,这不是一个好的场景,因为它们已经离开了代理的相对安全性,并且现在位于消费端点的 RAM 中。假设遇到了导致消费端点崩溃的异常 - 噗,所有消息都消失了。

如何解决这个问题?

您必须关闭 Auto-Ack,通常设置合理的预取计数也是一个好主意(通常 2-3 就足够了)。