I would like to set a timeout after which a dequeued message is automatically NACKed.
When I dequeue a message I wait until it is transfered over a socket and the other party confirms its reception.
Do I need to keep a list of Timers or can RMQ handle this automatically?
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 } }
The default connection timeout for the RabbitMQ connection factory is 600 seconds (at least in the Java client API), hence your 10 minutes. You can change this by specifying to the connection factory your timeout of choice.
In general, increasing prefetch will improve the rate of message delivery to consumers. Automatic acknowledgement mode yields best possible rate of delivery. However, in both cases the number of delivered but not-yet-processed messages will also increase, thus increasing consumer RAM consumption.
RabbitMQ Unacked Messages are the messages that are not Acknowledged. If a consumer fails to acknowledge messages, the RabbitMQ will keep sending new messages until the prefetch value set for the associated channel is equal to the number of RabbitMQ Unacked Messages count.
RabbitMQ Durable queues are those that can withstand a RabbitMQ restart. If a queue is not durable, all messages will be lost if RabbitMQ is shut down for any reason. For messages to survive restarts, both of these configurations must be true.
Yes. This is discussed in the official Python tutorial:
A timeout (30 minutes by default) is enforced on consumer delivery acknowledgement. This helps detect buggy (stuck) consumers that never acknowledge deliveries.
You can find more information available on the RabbitMQ documentation for Delivery Acknowledgement Timeout
However, this was not always the case. Older versions of RabbitMQ (at least through version 3.6.x) did not provide any sort of timeout mechanism for acknowledging messages. This was mentioned in older versions of the official Python tutorial:
There aren't any message timeouts; RabbitMQ will redeliver the message only when the worker connection dies. It's fine even if processing a message takes a very, very long time.
Section 3.1.8 of the AMQP 0-9-1 specification describes Acknowledgements, and is very clear that they can either be Automatic (the client doesn't have to do anything, messages are acknowledged as soon as they are delivered) or Explicit (the client must an Ack for each message or group of messages that it has processed).
Here's some past discussion from back in 2009 confirming this behavior.
The first reference to changing this behavior that I can see is this PR from April 2019. I'm not sure what version of the server that change was included in, but it sounds like the default was initially "no timeout", then 15 minutes in RabbitMQ 3.8.15, then 30 minutes in RabbitMQ 3.8.17 (where it remains as of October 2021).
So: This behavior is dependent on your version of RabbitMQ. Older versions required you to explicitly send NACKs after some interval. Newer versions have a default timeout.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With