rabbitmq Series Dead Letter Queue

Keywords: Java Jedis RabbitMQ Spring

1. What is the Dead Letter Queue

When a message becomes a dead letter in one queue, it is re publish ed to another switch, which is called a dead letter switch. A private switch delivers a dead letter to a queue, which is a dead letter queue.The principle is as follows:

There are three situations when a message becomes dead letter:

  • Message rejected (basic.reject / basic.nack), and requeue = false
  • Message TTL expires
  • Queue reaches maximum length

2. Manual Sign-Receive Response Mode

There are two reply modes, manual and automatic. Automatic reply means that consumers automatically tell the queue to delete a message when they consume one.The disadvantage of this is that no matter whether the consumption logic is successful or not, messages will be deleted, which will result in message loss.With a manual signature, the queue is manually told that the consumption was successful after the consumption logic was successfully processed, and then the queue deletes the message.

  1. Re-enable manual sign-in mode in consumer profile
spring.rabbitmq.listener.simple.acknowledge-mode = manual
  1. Manually sign in and modify consumer code after successful processing of consumer logic
@RabbitListener(queues = QUEUE_NAME)
    public void receiveMessage(Message message,@Headers Map<String,Object> headers, Channel channel) throws Exception {

        Jedis jedis = new Jedis("localhost", 6379);

        String messageId = message.getMessageProperties().getMessageId();
        String msg = new String(message.getBody(),"UTF-8");
        System.out.println("The message received is:"+msg+"==news id For:"+messageId);

        String messageIdRedis = jedis.get("messageId");

        if(messageId == messageIdRedis){
            return;
        }
        JSONObject jsonObject = JSONObject.parseObject(msg);
        String email = jsonObject.getString("email");
        String content = jsonObject.getString("timestamp");

        String httpUrl = "http://127.0.0.1:8080/email?email"+email+"&content="+content;
        // Return null if an exception occurs
        String body = HttpUtils.httpGet(httpUrl, "utf-8");
        //
        if(body == null){
            throw new Exception();
        }
        jedis.set("messageId",messageId);
        Long deliveryTag = (Long)headers.get(AmqpHeaders.DELIVERY_TAG);
		// Manual signing
        channel.basicAck(deliveryTag,false);
    }

3. Demonstration of Three Cases of Dead Letters

  • Message rejected

Let's continue to modify the consumer code and try to make exceptions happen when consumers are spending.Then reject the message in the catch block.

// Reject message to dead letter queue
channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);

We ran the program and found that ** When the message consumption was abnormal, the message in the queue "zb-byte1" was consumed, and there was a message in the dead-letter queue "dead-byte-zb" that was not consumed.** After the message goes to the Dead Letter queue, we can create a consumer to consume the message.The Dead Letter queue also needs to sign messages manually.

  • Message TTL expires

This mode is also called delayed consumption. A special classic case is that users in a commodity rush-buying system need to pay within 30 minutes after they get the commodity, otherwise the order is invalid.At this point, we can achieve this by expiring the message TTL, setting the queue message expiration time to 30 minutes, 30 minutes later publish to the Dead Letter queue, we consume the order status in the Dead Letter queue to determine whether the order is valid or not.

Very simple, we just need to set the valid time when configuring the Dead Letter switch

  @Bean
    public Queue queue(){

        Map<String,Object> map = new HashMap<>();
        map.put("x-dead-letter-exchange",BEI_EXCHANGE_NAME);
        map.put("x-dead-letter-routing-key",BEI_ROUTING_KEY);
        map.put("x-message-ttl",7200); // Queue expiration time
        Queue queue = new Queue(QUEUE_NAME,true,false,false,map);
        return queue;
    }
  • Queue reaches maximum length

Set the queue length:

 @Bean
    public Queue queue(){

        Map<String,Object> map = new HashMap<>();
        map.put("x-dead-letter-exchange",BEI_EXCHANGE_NAME);
        map.put("x-dead-letter-routing-key",BEI_ROUTING_KEY);
        map.put("x-max-length",3);
//        Map.put ("x-message-ttl, 7200); //Queue expiration time
        Queue queue = new Queue(QUEUE_NAME,true,false,false,map);
        return queue;
    }

Once set up, let's not start the consumer, then call the producer to send the message to the queue. When the message length is longer than 3, we find that the message goes into the dead letter queue.

Note: As mentioned earlier, queues cannot be modified, that is, queues that have already been created are set to expire at 7200s, and then we comment out that increasing the length of the queue is 3 code will cause errors. You must delete the queue in rabbitmq and rebuild the queue before you can.

If the article is helpful, please remember to pay attention to it.
Welcome to my public number: byte legend, daily push technical articles for your reference.

Posted by uluru75 on Sun, 22 Mar 2020 18:58:17 -0700