RabbitMQ消息是否有超时?

wkyowqbh  于 2023-10-20  发布在  RabbitMQ
关注(0)|答案(2)|浏览(145)

我想设置一个超时时间,超时后出队的消息将自动被否定应答。
当我将一条消息出队时,我会等待它通过套接字传输,并且另一方确认它的接收。
我需要保留一个定时器列表吗?或者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
    }
}
oo7oh9g9

oo7oh9g91#

是的。这在official Python tutorial中讨论:
对使用者传递确认强制超时(默认为30分钟)。这有助于检测那些从不承认交付的有缺陷的消费者。
您可以在RabbitMQ文档中找到有关交付确认的更多信息。
然而,情况并非总是如此。RabbitMQ的旧版本(至少到3.6.x版本)没有提供任何类型的超时机制来确认消息。这在older versions of the official Python tutorial中提到:
没有任何消息超时; RabbitMQ只会在worker连接断开时重新传递消息。即使处理一条消息需要很长很长的时间也没关系。
Section 3.1.8 of the AMQP 0-9-1 specification描述了Acknowledgements,并且非常清楚它们可以是 Automatic(客户端不需要做任何事情,消息一经传递就会被确认)或 Explicit(客户端必须为它处理的每个消息或消息组提供Ack)。
下面是2009年的一些past discussion,证实了这种行为。
我能看到的第一个改变这种行为的参考是2019年4月的this PR。我不确定这一更改包含在哪个版本的服务器中,但听起来默认值最初是“无超时”,然后是RabbitMQ 3.8.15中的15分钟,然后是RabbitMQ 3.8.17中的30分钟(截至2021年10月)。
因此:此行为取决于您的RabbitMQ版本。旧版本要求您在某个时间间隔后显式发送NACK。较新的版本具有默认超时。

5w9g7ksd

5w9g7ksd2#

现代版本的RabbitMQ有ack超时。因此,如果您的消费者在交付确认之前花费了大量时间,那么在更新到新版本时要小心。
如果使用者在超过超时值(默认为30分钟)的时间内未确认其传递,则其通道将关闭,并出现PRECONDITION_FANORTION通道异常。

**UPD:**更新后的文档中包含禁用超时的说明:

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

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

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

相关问题