我尝试了解AMQP协议的某些方面 . 目前我有RabbitMQ的项目并使用python pika库 . 所以问题是关于确认和消息预取 .
-
考虑我们只有消费者队列(确定这个队列被声明为独占) . 所以我理解正确:无论我是否使用ack标志?无论如何,我不应该同时处理多个消息,并且没有其他消费者可以采取其他一些仍然排队的消息 . 最好不要打开确认,因为这可能会降低AMQP服务器负载 .
-
如果没有确认,预取计数并不意味着什么 . 正确?
-
我不确定预取是如何工作的 . 我对新消息进行回调,并在其 finally 语句中确认或拒绝该消息 . 这是唯一的功能,无论预取计数有多大 - 无论如何,在当前消息完成之前,不会处理另一条消息 . 那么为什么我需要更改prefetch_count值呢?
提前致谢 .
1 回答
如果未设置
autoack
标志,如果您的应用程序在消息处理期间失败,则所有收到的消息都将丢失 . 如果这种情况非常罕见且消息丢失是您的应用程序中的适当选项(例如,但不限于,日志处理),您可以关闭autoack .是的,让
autoack
unset需要更简单的代理逻辑,因此它使用的资源更少 .对于
prefetch count
(和prefetch size
),这些选项告诉代理可能有多大的预先发送到客户端的有效负载到单个消息 . 通常它用于节省网络操作的时间以等待新消息 . 当prefetch size
使用的客户端将收到一个或多个总大小等于或小于预设预处理大小(和/或计数,更少)的消息 .它们设置的
prefetch count
和prefetch size
规则都已应用 . 当其中一个设置为零(未设置)时,将不会应用它们 .最重要的是, prefetching defines behavior to send messages in advance of more message that client has unacked .
结合这两个设置产生这样的东西:
Prefetch with messages count limit and sending messages in advance:
条件:
队列:N条消息x 1kb
预取:
prefetch-size=5kb, prefetch-count=4
Autoack:
off
工作流程:
Broker向客户端发送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队列,这样他们可能会再次被传递给这个或其他客户端 .
Prefetch with large messages:
条件:
队列:1条消息x 5Kb,N条消息x 1kb
预取:
prefetch-size=5kb, prefetch-count=2
Autoack:
off
工作流程:
代理向客户端发送1条消息(受
prefetch-size=5kb
限制),并将该消息标记为un-aked .客户端确认1消息 .
Broker有-1条消息未被激活,再次发送2条消息(受
prefetch-count=2
限制,请注意,只有第一条消息为5kb,其余为1kb)并且这些消息标记为未确认 .客户端确认1消息并失败 .
代理将从消息队列中移出已确认的消息,其余的未确认消息将再次移动到它们所属的队列,因此它们可能会再次传递给此客户端或其他客户端 .
With auto-ack:
条件:
队列:N条消息x 1kb
预取:
prefetch-size=5kb, prefetch-count=10
Autoack:
on
工作流程:
no-ack
设置为true时,prefetch-size
和prefetch-count
都被忽略(这是在RabbitMQ和AMQP文档中调用auto-ack功能的方式),消息将逐个发送到客户端,并在成功发送后从队列中删除 .注意,AMQP具有异步架构,因此在某些条件下,两个客户端可以同时接收单个消息 . 也可以将未发送的消息传递给同一客户端(特别是如果您有单个客户端) .
另外,请查看prefetch-size和prefetch-count官方文档,并尝试使用这些选项 .
P.S . :
autoack
基本上是no-ack
AMQP标志设置为true
.