In this article, we are going to learn what Is RabbitMQ dead letter exchange and how to configure it in simple steps.

Dead Letter exchange is a regular exchange. When a message cannot be delivered or unhandled by a consumer or Time to Live (TTL) of the message expires or the queue where you are sending the message has reached maximum capacity. In this all-conditions message is routed to a dead letter exchange.

The message is considered a dead letter message.

  • A message is negatively acknowledged by the consumer
  • The TTL of a message expires
  • The queue reaches capacity

Configuring Dead-Letter for RabbitMQ

In this part, we are going to create a dead letter exchange first and then create a dead letter queue. For doing this we are going to use RabbitMQ Web Console. To use this console, we need to enable this plugin it.

After enabling it will be accessible on this URL: – http://localhost:15672/

The default username :- guest and password: – guest

After login into RabbitMQ next, we are going to create we are going to create Exchange and queue.

Step 1:- Creating Exchange and queue

Create an Exchange with the name “Dead-Letter-exchange

Type: – Direct

Durability: – Durable Note: – For understanding it has given the name of the exchange as “Dead-Letter-exchange” it can be the custom name.

After adding exchange

Step 2:- Creating Queue

Create a Queue with the name “Dead-Letter-Queue

View After Creating Queue

Step 3:- Binding Exchange with Queue

Binding between “Dead-Letter-exchange” and “Dead-Letter-Queue” using routing key “dlx_key

For binding, we need to click on the queue name which you have created.

After clicking on the queue name just scroll below you will see the bindings tab.

Binding exchange to queue

For binding enter the exchange name “Dead-Letter-Queue” and routing key “dlx_key” and click on the bind button.

View After clicking on bind it should look like this

Configuring Classic Exchange and Queue

Step 1:- Create Direct Exchange

Create Direct Exchange with Name “demoexchange“.

Step 2:- Creating Queue

Create Queue with Name “demoqueue

Type: – Classic Queue

Durability: – Durable

Setting Arguments while Creating Queue

– Message TTL: – 60000  (60 sec)

Setting Argument x-message-ttl: “60000

– Dead letter exchange

Setting Argument x-dead-letter-exchange: “Dead-Letter-exchange

– Dead letter routing key

Setting Argument x-dead-letter-routing-key: “dlx_key

View After Creating a Queue with Arguments

Next, we are going to enter 1000 Messages in the queue.

This message in the queue will live for 60000 (60 sec) after that it will move to the dead letter queue with the help of the exchange name and routing key which we have provided when creating the queue.

Note: – x-message-ttl for the demo I have set to 60 sec.

After 60-sec values will be moved from the demo queue to Dead-Letter-queue.

Just keep seeing UI you can see the migrating message.

The main question arises of what to do with these messages in the dead letter queue right.

Solution

  • You can create a consumer for a dead letter queue read messages and take a decision.
  • you can do retry logic (adding a message from the dead letter queue to Main Queue where it came from) and maintain a counter to see if you have tried 2 to 3 times to read. if 3 times then process that message.

How to Configure Dead Letter Exchange from Code

using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Text;

namespace RequestRabbitMQ
{
    public class Directmessages
    {
        private const string UserName = "guest";
        private const string Password = "guest";
        private const string HostName = "localhost";

        public void SendMessage(int i)
        {
            //Main entry point to the RabbitMQ .NET AMQP client
            var connectionFactory = new RabbitMQ.Client.ConnectionFactory()
            {
                UserName = UserName,
                Password = Password,
                HostName = HostName
            };

            var connection = connectionFactory.CreateConnection();
            var channel = connection.CreateModel();
            var properties = channel.CreateBasicProperties();
            properties.Persistent = true;

            // Creating Dead letter Queue and Exchange
            channel.ExchangeDeclare("Dead-Letter-exchange", ExchangeType.Direct, true, false);
            channel.QueueDeclare("Dead-Letter-Queue", false, false, false, null);
            channel.ExchangeBind(destination: "Dead-Letter-exchange", source: "Dead-Letter-Queue", routingKey: "dlx_key");


            //Creating Exchange and Queue with Dead letter Arguments
            channel.ExchangeDeclare("demoexchange", ExchangeType.Direct, true, false);
            Dictionary<string, object> args = new Dictionary<string, object>()
             {
                 { "x-dead-letter-exchange", "Dead-Letter-exchange" },
                 { "x-dead-letter-routing-key", "dlx_key" },
                  { "x-message-ttl", "60000" },
             };

            channel.QueueDeclare("demoqueue", false, false, false, args);
            channel.ExchangeBind(destination: "demoexchange", source: "demoqueue", routingKey: "demokey");

            byte[] messagebuffer = Encoding.Default.GetBytes("Message" + i);

            channel.BasicPublish("demoexchange", "demokey", properties, messagebuffer);

            Console.WriteLine("Message Sent");
        }
    }
}

By Saineshwar

Microsoft MVP for Developer Technologies | C# Corner MVP | Code project MVP | Senior Technical Lead | Author | Speaker | Love .Net | Full Stack developer | Open source contributor.