RabbitMQ消息确认是否有超时时间?

31

我希望设置一个超时时间,在此之后,出列的消息将自动NACK。

当我出列一条消息时,我会等待它通过套接字传输,并且另一方确认已收到。

我需要保留计时器列表吗?还是RMQ可以自动处理?

private void Run()
{
    _rmqConnection = _queueConnectionFactory.CreateFactory().CreateConnection();

    _rmqReadchannel = _rmqConnection.CreateModel();

    _rmqReadchannel.QueueDeclare(QueueIdOutgoing(), true, false, false, null);

    _rmqReadchannel.BasicQos(0, 1, false);
    var consumer = new QueueingBasicConsumer(_rmqReadchannel);
    _rmqReadchannel.BasicConsume(QueueIdOutgoing(), false, consumer);
    while (true)
    {
        if (!_rmqReadchannel.IsOpen)
        {
            throw new Exception("Channel is closed");
        }
        var ea = consumer.Queue.Dequeue();
        string jsonData = Encoding.UTF8.GetString(ea.Body);
        if (OnOutgoingMessageReady != null)
        {
            OnOutgoingMessageReady(this, new QueueDataEventArgs(jsonData, ea.DeliveryTag));
        }
        //waiting for ACK from a different thread
    }
}
2个回答

47

是的。在官方Python教程中有讨论:

对于消费者接收确认,强制执行超时(默认为30分钟)。这有助于检测出永远不会确认接收的错误(卡住的)消费者。

您可以在RabbitMQ文档中找到更多关于传递确认超时的信息。

然而,这并非一直如此。旧版本的RabbitMQ(至少通过版本3.6.x)没有提供任何确认消息超时机制。在旧版本的官方Python教程中提到了这一点:

没有任何消息超时; 只有当工作连接断开时,RabbitMQ才会重新发送消息。即使处理一个消息需要很长时间,也没问题。

AMQP 0-9-1规范第3.1.8节描述了确认,并非常清楚地说明它们可以是自动(客户端不需要做任何事情,消息在传递时就被确认)或显式(客户端必须为其处理的每个消息或一组消息发送确认)。

这里有从2009年开始的过去讨论,确认了这种行为。

我能找到的第一个提到更改此行为的参考资料是来自2019年4月的这个 PR。我不确定该更改包含在哪个版本的服务器中,但听起来默认值最初是“无超时”,然后在RabbitMQ 3.8.15中为15分钟,然后在RabbitMQ 3.8.17中为30分钟(截至2021年10月目前仍然是如此)。

因此:此行为取决于您使用的RabbitMQ版本。旧版本需要您在一定时间间隔后明确发送NACKs。新版本有一个默认超时时间。


2
不否认此答案的有效性(在发布时是正确的),但自那时以来,RabbitMQ的新版本已实现了“消费者确认超时”(默认为30分钟)并严格执行。请参考上面@Egor的答案。 - leonidos79
2
@leonidos79 感谢您指出这一点;我已经更新了我的答案,以考虑到当前行为和默认行为随时间改变的事实。 - Donut

17
现代版本的RabbitMQ有确认超时。因此,如果您有消费者在交付确认之前花费了很长时间,请小心更新到新版本。

如果消费者在超时值(默认为30分钟)内未确认其交付,则其通道将被关闭,并出现PRECONDITION_FAILED通道异常。

更新: 更新的文档包含禁用超时的说明:

可以使用advanced.config来停用超时。但不建议这样做:

%% advanced.config
[
  {rabbit, [
    {consumer_timeout, undefined}
  ]}
].

不要完全禁用超时,考虑使用一个较高的值(例如几个小时)。

谢谢,那么这个可以设置到最大吗?最大值是多少? - toha
@toha 我不知道这个属性的最大大小是多少,兔子文档中没有任何相关信息。但我刚刚注意到兔子文档中有一个更新,可以将所有超时时间都取消激活。我已经在我的回答中添加了这个信息。 - Egor
非常好。我会试着做几个小时。 试验后,希望不再发生任何事情。 - toha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接