我想设置一个超时时间,超时后出队的消息将自动被否定应答。
当我将一条消息出队时,我会等待它通过套接字传输,并且另一方确认它的接收。
我需要保留一个定时器列表吗?或者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条答案
按热度按时间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。较新的版本具有默认超时。
5w9g7ksd2#
现代版本的RabbitMQ有ack超时。因此,如果您的消费者在交付确认之前花费了大量时间,那么在更新到新版本时要小心。
如果使用者在超过超时值(默认为30分钟)的时间内未确认其传递,则其通道将关闭,并出现PRECONDITION_FANORTION通道异常。
**UPD:**更新后的文档中包含禁用超时的说明:
可以使用advanced.exe停用超时。不建议这样做:
与其完全禁用超时,不如考虑使用一个较高的值(例如,几个小时)。