Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting a long timeout for RabbitMQ ack message

I was wondering if this is possible. I want to pull a task from a queue and have some work that could potentially take anywhere from 3 seconds or longer (possibly) minutes before an ack is sent back to RabbitMQ notifying that the work has been completed. The work is done by a user, hence this is why the time it takes to process the job varies.

I don't want to ack the message immediately after I pop off the queue because I want the message to be requeued if no ack is received. Can anyone give me any insights into how to solve my problem?

like image 935
Wanged Avatar asked Jun 24 '14 00:06

Wanged


People also ask

How do you increase RabbitMQ timeout?

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.

How do I set consumer timeout on RabbitMQ?

You can dynamically set the consumer_timeout value by running the following command on the RabbitMQ server: rabbitmqctl eval 'application:set_env(rabbit, consumer_timeout, 36000000). ' This will set the new timeout to 10 hrs (36000000ms).

How does RabbitMQ ack work?

basic. ack for a persistent message routed to a durable queue will be sent after persisting the message to disk. The RabbitMQ message store persists messages to disk in batches after an interval (a few hundred milliseconds) to minimise the number of fsync(2) calls, or when a queue is idle.

What does ack mean in RabbitMQ?

Acknowledgements (Consumer Acknowledgements, Ack, Delivery Acknowledgements) When RabbitMQ delivers a message to a consumer, it needs to know when to consider the message successfully sent. An ack will acknowledge one or more messages, which tells RabbitMQ that a message/messages has been handled.


1 Answers

Having a long timeout should be fine, and certainly as you say you want redelivery if something goes wrong, so you want to only ack after you finish.

The best way to achieve that, IMO, would be to have multiple consumers on the queue (i.e. multiple threads/processes consuming from the same queue). That should be fine as long as there's no particular ordering constraint on your queue contents (i.e. the way there might be if the queue were to contain contents representing Postgres data that involves FK constraints).

This tutorial on the RabbitMQ website provides more info (Python linked, but there should be similar tutorials for other languages): https://www.rabbitmq.com/tutorials/tutorial-two-python.html

Edit in response to comment from OP:

What's your heartbeat set to? If your worker doesn't acknowledge the heartbeat within the set period of time, the server will consider the connection to be dead.

Not sure which language you're using, but for Java you would use the setRequestedHeartbeat method to specify the heartbeat.

The way you implement your workers, it's vital that the heartbeat can still be sent back to the RabbitMQ server. If something blocks the client from sending the heartbeat, the server will kill the connection after the time interval expires.

like image 186
khampson Avatar answered Oct 21 '22 07:10

khampson