Dead letter queue of RabbitMQ

1, What is a dead letter queue?

Dead letter queue is a message mechanism in RabbitMQ. Dead letter messages will be specially processed by RabbitMQ. If dead letter queue is configured, dead letter messages will be thrown into dead letter delivery queue. If not configured, dead letter messages will be discarded.

2, Situation of dead letter

  1. The message is negatively acknowledged (reject the message using channel.basicNack or channel.basicReject), and message resending is not performed (set the request property to false)
  2. The message's survival time in the queue exceeds the set TTL time (if the message or queue exceeds the set time, the message will enter the dead letter queue)
  3. The message in the message queue has exceeded the maximum length of the queue

3, What is TTL?

The expiration time TTL indicates that the expected time can be set for the message, which can be accepted by consumers within this time, but after this message, the message will be deleted automatically. You can set TTL for messages and queues in RabbitMQ. At present, two methods can be set

1. Queue setting TTL

By setting TTL on the queue, all messages in the queue have a unified expiration time

 @Bean
    public Queue TestQueueTTL(){
        // Set the message expiration time to 7s
        return QueueBuilder.durable("test_ttl_queue").withArgument("x-message-ttl",7000).build();
    }

2. Message setting TTL

By setting the expiration time separately for each message, the freedom is higher

@GetMapping("/test/message/ttl")
    public String TestMessageTTL(){
        MessageProperties properties = new MessageProperties();
        // Set the message expiration time to 3sz`
        properties.setExpiration("7000");
        Message m = new Message("Test the message through 7 s Will it disappear later".getBytes(),properties);
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend("TestFanoutExchange",null,m,correlationData);
        return "Successfully sent TTL news";
    }

be careful!!!
If there are non TTL messages that have not been consumed in the message queue to be sent, the message with the separately set expiration time will not expire and disappear, but will become a permanent message (the reason is unknown)

4, Dead letter queue

1. Principle

DLX, fully known as dead letter exchange, can also be called dead letter switch. When a message becomes a dead letter message in a queue, the message can be re sent to another switch. The bound switch is called a dead letter switch, and the queue bound to the switch is called a dead letter queue.

2. Realization

  1. Producer sends message
 @GetMapping("/test/message/ttl")
    public String TestMessageTTL(){
        MessageProperties properties = new MessageProperties();
        Message m = new Message("Send a dead letter message".getBytes(),properties);
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend("TestFanoutExchange",null,m,correlationData);
        return "Successfully sent TTL news";
    }
  1. Define the switch and queue, bind the dead letter switch to the queue, and then talk about binding the dead letter switch to the dead letter queue
@Configuration
public class DirectRabbitConfig {

    @Bean
    public FanoutExchange TestFanoutExchange(){
        return new FanoutExchange("TestFanoutExchange",true,false);
    }
    
    /**
     * Test queue TTL
     * @return
     */
    @Bean
    public Queue TestQueueTTL(){
        // Set the message expiration time to 7s
        Map<String,Object> map = new HashMap<>();
        map.put("x-message-ttl",7000);
        map.put("x-dead-letter-exchange","TestDLX");
        map.put("x-dead-letter-routing-key","TestDLXRouting");
        return QueueBuilder.durable("test_ttl_queue").withArguments(map).build();
    }

    @Bean
    public Binding TestQueueTTLBinding(){
        return BindingBuilder.bind(TestQueueTTL()).to(TestFanoutExchange());
    }


     /**
     * The switch is a dead letter switch, which is similar to test_ttl_queue binding
     * @return
     */
    @Bean
    public DirectExchange TestDLX(){
        return new DirectExchange("TestDLX",true,false);
    }

    /**
     * This queue is a dead letter queue, which is bound with the dead letter switch
     * @return
     */
    @Bean
    public Queue TestDLXQueue(){
        return new Queue("TestDLXQueue",true);
    }

    @Bean
    public Binding TestDLXBinding(){
        return BindingBuilder.bind(TestDLXQueue()).to(TestDLX()).with("TestDLXRouting");
    }
}

  1. Only one consumer is defined to receive messages from the dead letter queue (because there is no consumer defined for the normal queue, the messages in the normal queue will be automatically converted into dead letter messages and sent to the dead letter switch after the expiration time)
@Component
public class DirectReceiver {

    @RabbitHandler
    @RabbitListener(queues = "TestDLXQueue")
    public void receive2(Message message, Channel channel) {
        // Normal consumption of messages
        System.out.println(message);

        // Manual answer Broker
        try {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

Tags: Java RabbitMQ Distribution message queue

Posted on Sat, 06 Nov 2021 23:31:07 -0400 by kbaker