[Deep Understanding of RabbitMQ] Dead Letter Queue

Keywords: RabbitMQ Java Attribute

Dead Letter Queue

 

Dead letter queue

DLX is also called Dead-Letter-Exchange.

Dead letter queue refers to the message on the queue becomes dead letter and can be sent to another switch, which is DLX.

 

In general, there are several situations that can turn into dead letters:

  • Messages are rejected (Basic.reject or basic.nack) and the requeue parameter is set to false
  • Message expiration sets message TTL
  • Maximum queue length

Dead-letter switches are normal switches that can be designated on any queue. In fact, there is no difference between dead-letter exchanges and general exchanges, but the attribute of dead-letter exchanges has been added. If there is a dead letter on the queue, RabbitMq will deliver the dead letter message to the set DLX, and then be routed to a queue, which is the dead letter queue.

 

The process is as follows:

                 

 

Producer:

import java.util.HashMap;
import java.util.Map;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;



public class Producer {
    public static void main(String[] args) throws Exception {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setVirtualHost("/");
        connectionFactory.setHost("xxxx");
        connectionFactory.setUsername("xxx");
        connectionFactory.setPassword("xxx");
        connectionFactory.setPort(5672);
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        String exchangeName = "normal_exchange";
        String routingkey = "dlx.dlx";
        String msg = "test dlx message";
        String queueName = "normal_queueName";
        Map<String,Object>map =new HashMap<>();
        //Note: The key x-dead-letter-exchange is fixed and the value is customized.
        map.put("x-dead-letter-exchange","exchange.dlx");
        //Note: arguments need to be declared on the queue and declarations will not work on the switch.
        channel.queueDeclare(queueName, true, false, false, map);
        channel.exchangeDeclare(exchangeName,"direct",true,false,null);
        channel.queueBind(queueName,exchangeName,"dlx.dlx");
        for (int i = 0; i < 3; i++) {
            // deliveryMode=2 persistence, expiration message validity time
            AMQP.BasicProperties properties=new AMQP.BasicProperties().builder()
                    .deliveryMode(2)
                    .contentEncoding("utf-8")
                    .expiration("7000")
                    .build();
            channel.basicPublish(exchangeName, routingkey, true, properties, msg.getBytes());
        }
    }
}

 

Consumer:



import java.io.IOException;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class Consumer {
    public static void main(String[] args) throws Exception {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setVirtualHost("/");
        connectionFactory.setHost("xxxx");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("xxxx");
        connectionFactory.setPassword("xxxx");
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        //Dead Message Switch Statement
        channel.exchangeDeclare("exchange.dlx","topic",true,false,null);
        //Dead letter queue statement
        channel.queueDeclare("queue.dlx",true,false,false,null);
        //Rougkey is specified as #, which means that as long as the route to the dead-letter queue is received.
        channel.queueBind("queue.dlx","exchange.dlx","#");
        
        channel.basicConsume("queue.dlx", false, "myConsumer Tag", new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) throws IOException {
                  String routingKey = envelope.getRoutingKey();
                  String convernType = properties.getContentType();
                  long deliveryTag = envelope.getDeliveryTag();
                  System.out.println("routingKey:"+routingKey+",convernType:"+convernType+",deliveryTag:"+deliveryTag+",Msg body:"+new String(body));
                  channel.basicAck(deliveryTag, false);
            }
           
        });

    }
}

 

As you can see from the above code:

The message arrives at the normal queue through normal_exchange.  

 map.put("x-dead-letter-exchange","exchange.dlx");
 //Note: arguments need to be declared on the queue and declarations will not work on the switch.
 channel.queueDeclare(queueName, true, false, false, map);

 

The normal queue normal_queue declares that an x-dead-letter-exchange is set under the following parameters. When the message expires, it sends the message to the dead-letter exchange.dlx

A queue queue.dlx is bound under the Dead Message Switch

 channel.exchangeDeclare("exchange.dlx","topic",true,false,null);
        //Dead letter queue statement
        channel.queueDeclare("queue.dlx",true,false,false,null);
        //Rougkey is specified as #, which means that as long as the route to the dead-letter queue is received.
        channel.queueBind("queue.dlx","exchange.dlx","#");

Finally, the message is sent to the dead-letter queue, consumers, consumption queue.dlx on the dead-letter queue message can be.

      channel.basicConsume("queue.dlx", false, "myConsumer Tag", new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) throws IOException {
                  String routingKey = envelope.getRoutingKey();
                  String convernType = properties.getContentType();
                  long deliveryTag = envelope.getDeliveryTag();
                  System.out.println("routingKey:"+routingKey+",convernType:"+convernType+",deliveryTag:"+deliveryTag+",Msg body:"+new String(body));
                  channel.basicAck(deliveryTag, false);
            }
           
        });

 

 

Posted by debuitls on Wed, 21 Aug 2019 23:13:13 -0700