【问题标题】:Is there a timeout for acking RabbitMQ messages?响应 RabbitMQ 消息是否有超时?
【发布时间】:2015-05-30 13:49:21
【问题描述】:

我想设置一个超时时间,之后出队的消息会自动被 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
    }
}

【问题讨论】:

    标签: c# rabbitmq


    【解决方案1】:

    是的。这在official Python tutorial 中进行了讨论:

    对消费者交付确认强制执行超时(默认为 30 分钟)。这有助于检测从不确认交付的错误(卡住)消费者。

    您可以在 Delivery Acknowledgement Timeout 的 RabbitMQ 文档中找到更多信息

    但是,情况并非总是如此。 RabbitMQ 的旧版本(至少到 3.6.x 版)没有提供任何类型的超时机制来确认消息。 older versions of the official Python tutorial中提到了这一点:

    没有任何消息超时; RabbitMQ 只会在工作连接断开时重新传递消息。即使处理消息需要非常非常长的时间也没关系。

    Section 3.1.8 of the AMQP 0-9-1 specification 描述了确认,并且很清楚它们可以是自动的(客户端无需执行任何操作,消息在传递后立即得到确认)或 显式(客户端必须为它处理的每条消息或消息组提供一个 Ack)。

    这里有一些 2009 年的 past discussion 证实了这种行为。

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

    所以:此行为取决于您的 RabbitMQ 版本。旧版本要求您在一段时间后显式发送 NACK。较新的版本有默认超时。

    【讨论】:

    • 在不反对这个答案的有效性(在发布时是正确的)的情况下,较新版本的 RabbitMQ 从那时起已经实现了“消费者确认超时”(默认为 30 分钟),并且正在执行它严格。请参考上面@Egor 的回答。
    • @leonidos79 感谢您指出这一点;我更新了我的答案,以考虑当前行为和默认行为随时间发生变化的事实。
    【解决方案2】:

    RabbitMQ 的现代版本有ack timeout。 因此,如果您的消费者在交付确认之前花费大量时间,请谨慎更新新版本。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-15
      • 1970-01-01
      • 2011-02-17
      • 1970-01-01
      • 2012-02-27
      • 1970-01-01
      • 2018-11-11
      • 1970-01-01
      相关资源
      最近更新 更多