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); } });