docker+springboot+rabbitmq to implement dead letter queue

Keywords: Programming RabbitMQ Docker SpringBoot Spring

1. Download and start rabbitmq

docker pull hub.c.163.com/library/rabbitmq:3-management

docker run -d -p 5672:5672 -p 15672:15672 --name mymq hub.c.163.com/library/rabbitmq:3-management

#web access path ip:15672
#User name: guest password: Guest

2. Introduce dependency into the project of springboot

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

configuration information

spring:
  rabbitmq:
    host: 192.168.1.1
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    publisher-confirms: true
    listener:
      simple:
        retry:
          enabled: true # Allow message consumption to fail retries
          max-attempts: 3 # Message consumption up to 3 times
          initial-interval: 1000 # Message multiple consumption interval 1 second
        default-requeue-rejected: false # Set to false, the message will be discarded or republished to the dead letter queue

3. Write configuration information of dead letter queue

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

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

/**
 * Configuration of dead letter queue
 *
 * <p>The dead letter queue is actually,
 * When our business queue fails to handle (such as throwing exceptions and reaching the upper limit of retry),
 * It will resend the message to another Exchange(Dead Letter Exchanges),
 * The Exchange is then redirected to another queue according to the routingKey,
 * Reprocess the message in this queue. </p>
 */
@Configuration
public class RabbitDeadLetterConfig {

    public static final String DEAD_LETTER_EXCHANGE = "TEXT_DLE";
    public static final String DEAD_LETTER_TEST_ROUTING_KEY = "TEST_RK_DL";
    public static final String DEAD_LETTER_REDIRECT_ROUTING_KEY = "TEXT_RK_RJ";
    public static final String DEAD_LETTER_QUEUE = "TEXT_QUEUE_DLR";
    public static final String REDIRECT_QUEUE = "TEXT_QUEUE_RJ";

    /**
     * Switch defining dead letter queue
     * @return
     */
    @Bean
    public Exchange deadLetterExchange() {
        return ExchangeBuilder.directExchange(DEAD_LETTER_EXCHANGE).durable(true).build();
    }

    /**
     * Define dead letter queue
     * @return
     */
    @Bean
    public Queue deadLetterQueue() {
        Map<String, Object> map = new HashMap<>(2);
        map.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE);
        // Exception thrown by dead letter queue routingKey of redirection queue
        map.put("x-dead-letter-routing-key", DEAD_LETTER_REDIRECT_ROUTING_KEY);
        return QueueBuilder.durable(DEAD_LETTER_QUEUE).withArguments(map).build();
    }

    @Bean
    public Queue rejectQueue() {
        return new Queue(REDIRECT_QUEUE, true);
    }

    /**
     * Bind dead letter queue to dead letter switch
     * @return
     */
    @Bean
    public Binding deadLetterBinding() {
        return new Binding(DEAD_LETTER_QUEUE,  Binding.DestinationType.QUEUE,
                DEAD_LETTER_EXCHANGE, DEAD_LETTER_TEST_ROUTING_KEY, null);
    }

    /**
     * Bind redirection queue to Exchange of dead letter queue through routingKey
     * @return
     */
    @Bean
    public Binding redirectBinding() {
        return new Binding(REDIRECT_QUEUE, Binding.DestinationType.QUEUE,
                DEAD_LETTER_EXCHANGE, DEAD_LETTER_REDIRECT_ROUTING_KEY, null);
    }

}

4. The sender who wrote the message

import com.carter.car.rabbitmq.config.RabbitDeadLetterConfig;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class DeadLetterSender {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void send(String msg) {
        rabbitTemplate.convertAndSend(
                RabbitDeadLetterConfig.DEAD_LETTER_EXCHANGE,
                RabbitDeadLetterConfig.DEAD_LETTER_TEST_ROUTING_KEY,
                msg
        );
    }

}

5. Message consumers writing dead letter queue

import com.carter.car.rabbitmq.config.RabbitDeadLetterConfig;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;

/**
 * Dead letter queue consumer
 */
@Component
@RabbitListener(queues = RabbitDeadLetterConfig.DEAD_LETTER_QUEUE)
public class DeadLetterConsumer {

    @RabbitHandler
    public void handler(@Payload String msg) {
        System.out.println("DeadLetterConsumer receive msg:" + msg);
        throw new RuntimeException("i am a error.");
    }

}

6. Write message consumers of redirection queue

import com.carter.car.rabbitmq.config.RabbitDeadLetterConfig;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * Redirect queue consumer
 */
@Component
@RabbitListener(queues = RabbitDeadLetterConfig.REDIRECT_QUEUE)
public class RedirectQueueConsumer {

    @RabbitHandler
    public void handler(String msg) {
        System.out.println("RedirectQueueConsumer receive msg:" + msg);
    }

}

7. Write test class

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest
@RunWith(SpringRunner.class)
public class DeadLetterTest {

    @Autowired
    private DeadLetterSender deadLetterSender;

    @Test
    public void testSend() {
        deadLetterSender.send("hello world!");
    }

}

8. Start the springboot project, and then run the test to send the message.
Reference resources:
Cancel the order 30 minutes after dead letter queue
Dead letter queue application scenario

Posted by Wolverine68 on Sat, 28 Mar 2020 07:31:46 -0700