Rabbitmq Ack or Nack, leaving messages on the queue
This is how my company does it: If a message fails (for any reason) we nack the message into a holding queue where it sits for 10 seconds, it then gets put back into the queue to be retried. We do this loop up to 10 times, if the message is nacked 10 times then we assume it is a failure we can't recover from and we put it into a permanent dead-letter queue for investigation.
Here is the diagram:
Related videos on Youtube
level_zebra
Updated on June 04, 2022Comments
-
level_zebra almost 2 years
I have been playing around with RabbitMq.net and the message acknowledgements. If the consumer is able to process the message you can send back an ack in the form of
channel.BasicAck(ea.DeliveryTag, false);
which will take it off the queue.
But what about if the message was unable to be processed ? maybe a temporary outage and you don't want the message taken off the queue just put to the back and carry on with the next message?
I have tried using
channel.BasicNack(ea.DeliveryTag, false, true);
but the next time round its still getting the same message and not moving to the next message in the queue
my complete code is
class Program { private static IModel channel; private static QueueingBasicConsumer consumer; private static IConnection Connection; static void Main(string[] args) { Connection = GetRabbitMqConnection(); channel = Connection.CreateModel(); channel.BasicQos(0, 1, false); consumer = new QueueingBasicConsumer(channel); channel.BasicConsume("SMSQueue", false, consumer); while (true) { if (!channel.IsOpen) { throw new Exception("Channel is closed"); } var ea = consumer.Queue.Dequeue(); string jsonified = Encoding.UTF8.GetString(ea.Body); var message = JsonConvert.DeserializeObject<SmsRecords>(jsonified); if (ProcessMessage()) channel.BasicAck(ea.DeliveryTag, false); else channel.BasicNack(ea.DeliveryTag, false, true); } } private static bool ProcessMessage() { return false; } public static IConnection GetRabbitMqConnection() { try { var connectionFactory = new ConnectionFactory { UserName = "guest", Password = "guest", HostName = "localhost" }; return connectionFactory.CreateConnection(); } catch (Exception ex) { Console.WriteLine(ex.Message); return null; } } }
-
level_zebra about 9 yearsI resolved this by using a subscription and then calling BasicDeliverEventArgs basicDeliveryEventArgs = subscription.Next();
-
user2864740 over 8 yearsHow did using Subscription 'fix' the issue of keeping on running into the same messages? Either NoAck mode is on (and the server auto-acks) or Ack was sent to acknowledge processing of the message - both are wrong if the message couldn't be processed in some valid fashion but "shouldn't be lost". If Acks aren't sent then the messages will 'reappear' once the channel is closed. I suspect that the code with the Subscription simply used a larger Prefetch or something else.. (with RabbitMQ > 2.7 you can Nack-requeue to effectively put messages "to the back" of the prefetch buffer).
-
-
Jerald Baker about 4 yearsHow do you nack message "into a holding queue"? doesn't it automatically get re-queued in the original queue?