2017-06-14 253 views
0

我有以下配置的RabbitMQ当消费者从RabbitMQ的,哪里信道获取消息预取消息驻留

prefetchCount:1 ACK模式:自动。

我有一个交换和一个队列连接到该交换和一个消费者连接到该队列。根据我的理解,下面的步骤将发生如果队列有多条消息。

  1. 在一个通道上队列写入数据。
  2. 由于ack模式是自动的,只要队列在通道上写入消息,消息就会从队列中删除。
  3. 消息传递给消费者,消费者开始执行该数据。
  4. 由于Queue已经得到了前一条消息的确认,Queue将下一个数据写入Channel。

现在,我的疑问是,假设消费者还没有完成之前的数据呢。下一个数据队列写入通道会发生什么?

另外,假设prefetchCount是10,并且我只有一次消费者连接队列,这10个消息将驻留在哪里?

回答

1

您描述的场景是在RabbitMQ文档中提到的场景,详细描述见this blog post。具体来说,如果您设置了足够大的预取计数,并且发布速率相对较低,那么RabbitMQ服务器就会变成一个奇特的网络交换机。当确认模式设置为自动时,预取限制被有效禁用,因为从来没有未确认的消息。通过自动确认,消息在交付后立即得到确认。这与具有任意大的预取计数相同。

预取大于1时,消息存储在客户端库的缓冲区中。确切的数据结构将取决于所使用的客户端库,但据我所知,所有实现都将消息存储在RAM中。此外,使用自动确认功能,您无法知道特定消费者实际阅读和处理消息的时间。

所以,有几个外卖这里:

  1. 预取限制是无关紧要的自动确认,因为从未有任何未确认的消息,因此使用时
  2. 自动确认没有多大意义消费者
  3. 当auto-ack处于关闭状态时,或者使用autoack = on时,将进行足够大的预取,这将导致消息代理不执行任何排队,而仅执行路由。

现在,这里有一些专家意见。我发现消息代理的整体概念“推动”消息有点倒退,出于这个原因,很难正确配置,并且不清楚它的好处是什么。队列系统自然适合拉式系统。当处理完当前消息后,处理器可以向代理询问下一条消息。这种方法将确保负载自然平衡,并且在处理器断开连接或被断开时消息不会丢失。

因此,我的建议是放弃使用消费者,并切换到使用basic.get

+0

很好的答案,清除了很多疑惑,将切换到pull.One更多的事情,在我们目前的项目中,我们有以下场景,假设在队列中的任何时候我们有记录如下A-> B-> C,记录C只能被处理了,A已经被处理了。这个实现是一样的吗?如果我们发现它的前任处理过的记录尚未处理,那么我们再次排队记录(而不是发送-nack,将通过交换进行排队)。这将使我们的队列记录为C-> A-> B,现在C将在A之后处理。 – Nishat

+0

感谢您的赞扬!如果您有其他问题,我建议您将问题张贴为新问题,以便更方便地索取答案。我会评论说,所描述的情况似乎有点复杂的消息。 – theMayer

相关问题