AMQP:确认和预取

时间:2014-02-08 22:22:19

标签: python rabbitmq amqp pika

我尝试了解AMQP协议的某些方面。目前我有RabbitMQ的项目并使用python pika库。所以问题是关于确认和消息预取。

  1. 考虑我们只有消费者的队列(确定这个队列被声明为独占)。所以我理解正确:无论我是否使用ack标志?无论如何,我不应该同时处理多个消息,并且没有其他消费者可以采取其他一些仍然排队的消息。最好不要打开确认,因为这可能会降低AMQP服务器的负载。

  2. 如果没有确认,预取计数并不意味着什么。正确的吗?

  3. 我不确定预取是如何工作的。我对新消息进行回调,并在 finally 语句中确认或拒绝该消息。这是唯一的功能,无论预取计数有多大 - 无论如何,在当前消息完成之前,不会处理另一条消息。那么为什么我需要更改prefetch_count值?

  4. 提前感谢。

1 个答案:

答案 0 :(得分:27)

如果未设置autoack标志,如果您的应用程序在消息处理期间失败,则所有收到的消息都将丢失。如果这种情况非常罕见且消息丢失是您的应用程序中的适当选项(例如,但不限于,日志处理),您可以关闭autoack。

是的,让autoack取消设置需要更简单的代理逻辑,因此它使用的资源更少。

对于prefetch count(和prefetch size),这些选项告诉代理可能有多大的预先发送到客户端的有效负载到单个消息。通常它用于节省网络操作的时间以等待新消息。当prefetch size使用过的客户端将收到一个或多个总大小等于或小于预设预设大小(和/或计数,更少)的消息。

应用了prefetch countprefetch size规则。当其中一个设置为零(未设置)时,将不会应用它。

最重要的是,预取定义了在客户端已解除支持的更多消息之前发送消息的行为

结合这两个设置产生如下:

预取消息计数限制并提前发送消息:

条件:

  • 队列:N条消息x 1kb
  • 预取prefetch-size=5kb, prefetch-count=4
  • Autoack off

工作流程:

  • 代理向客户端发送4条消息(受prefetch-count=4限制)。 4条消息将被标记为un-acked并从队列中移出(因此它们不会被传递给其他客户端)。
  • 客户端确认1消息。
  • Broker已释放-1条消息(删除该消息)并向客户端再发送1条消息(+1 un-aked,-1来自队列,而客户端已经有3条消息未被确认)。
  • 客户端确认其余3条消息+新发送的消息。
  • 经纪人有4条消息未被激活,再次发送4条消息,+ 4未发送,-4从队列发送。
  • 客户端确认1消息并失败。
  • Broker将-1 un-acked,然后将其余的un-acked移回队列,因此-3 un-aked和+3队列,这样他们可能会再次被送到这个或其他客户端。

使用大型邮件进行预取:

条件:

  • 队列:1条消息x 5Kb,N条消息x 1kb
  • 预取prefetch-size=5kb, prefetch-count=2
  • Autoack off

工作流程:

  • 经纪人向客户发送1条消息(受prefetch-size=5kb限制),并将该消息标记为未支持。
  • 客户端确认1消息。
  • Broker有-1条消息未被激活,再次发送2条消息(受prefetch-count=2限制,请注意,只有第一条消息为5kb,其余为1kb),这些消息标记为未确认。
  • 客户端确认1消息并失败。
  • Broker将从消息队列中移出已确认的消息,其余的未确认消息将再次移动到他们所属的队列,因此可能会再次将其传递给此客户端或其他客户端。

使用auto-ack:

条件:

  • 队列:N条消息x 1kb
  • 预取prefetch-size=5kb, prefetch-count=10
  • Autoack on

工作流程:

  • prefetch-size设置为true时,prefetch-countno-ack都被忽略(这就是在RabbitMQ和AMQP文档中调用auto-ack功能的方式),消息将被发送到客户端1成功发送后,从队列中删除。

注意,AMQP具有异步架构,因此在某些条件下,两个客户端可以同时收到单个消息。也可以将未发送的消息传递给同一客户端(特别是如果您有单个客户端)。

另外,请查看prefetch-sizeprefetch-count官方文档,并尝试使用这些选项。

P.S。:autoack基本上no-ack AMQP标志设置为true