RabbitMQ 死信交换机TTL演示demo

源码在文章末尾

1. 前置学习知识

RabbitMQ消费者确认消息入门演示

2. 什么是死信交换机

满足死信交换机有三种情况分别是 :

  • 消费者使用basic.reject或 basic.nack声明消费失败,并且消息的requeue参数设置为false

  • 消息是一个过期消息,超时无人消费

  • 要投递的队列消息满了,无法投递

3.死信队列和失败消息队列的区别

   在上篇文章讲到的RepublishMessageRecoverer因为消费者内部出现异常, 导致重试次数耗尽, 为了消息不会丢弃, 我们直接将消费者消息发送到(error.direct)失败交换机中

   如下图所示这次我们所讲的死信交换机种, 我们发现明显的差别, 在死信中, 异常消息没有到达消费者, 而是直接到达了交换机(dl.direct)

RabbitMQ 死信交换机TTL演示demo_第1张图片

 4.TTL(存活时间/过期时间)

一个队列中的消息如果超时未消费,则会变为死信,超时分为两种情况:

  • 消息所在的队列设置了超时时间

  • 消息本身设置了超时时间

RabbitMQ 死信交换机TTL演示demo_第2张图片

下面我们用代码演示如何接收超时死信的死信交换机的消息

4.1定义死信队列

    //-----------------死信队列---------------------------
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "dl.queue", durable = "true"),
            exchange = @Exchange(name = "dl.direct"),
            key = "dl"
    ))
    public void listenDlQueue(String msg){
        log.info("消费者接收到了dl.queue的延迟消息:{}", msg);
    }
    //-----------------死信队列---------------------------

4.2声明一个指定TTL的队列

值得注意的是, 在声明队列时, 我们要指定对应的死信交换机才可以, 而且因为设置了10秒的超时时间, 也就是在十秒之后会收到死信队列的监听消息


    @Bean
    public DirectExchange ttlDirectExchange(){
        return new DirectExchange("ttl.direct");
    }

    @Bean
    public Queue ttlQueue(){
        return QueueBuilder
                // 指定队列名称,并持久化
                .durable("ttl.queue")
                // 设置队列的超时时间,10秒
                .ttl(10000)
                // 指定死信交换机
                .deadLetterExchange("dl.direct")
                //指定死信的RoutingKey
                .deadLetterRoutingKey("dl")
                .build();
    }

    @Bean
    public Binding  ttlBinding(){
        return BindingBuilder.bind(ttlQueue()).to(ttlDirectExchange()).with("ttl");
    }

4.3发送消息

    @Test
    public void testTTLMessage() {
        // 1.准备消息
        Message message = MessageBuilder
                .withBody("hello, ttl messsage".getBytes(StandardCharsets.UTF_8))
                .setDeliveryMode(MessageDeliveryMode.PERSISTENT)
                .build();
        // 2.发送消息
        rabbitTemplate.convertAndSend("ttl.direct", "ttl", message);
        // 3.记录日志
        log.info("消息已经成功发送!");
    }

4.4运行结果

我们发消息的时间在28秒的时候

之前我们设置了10秒的超时时间, 所以在第38秒的时候, 我们的死信队列成功收到了消息

之所以消息会进入死信队列是因为没有消费者去消费这条消息, 如果正常想正常消费可以加入如下代码


    /**
     * 如果不想走死信队列就走如下代码, 因为消费者已经消费后就不会进入死信队列
     * @param msg
     */
    @RabbitListener(queues = "ttl.queue")
    public void ttlQueue(String msg){
        log.info("接受ttl的消息, 为了不让死信队列去监听而定义的:{}", msg);
    }
    

 链接:https://pan.baidu.com/s/1il41ywFnYM4_q3MU9GN_MQ 
提取码:heng

你可能感兴趣的:(RabbitMQ教程,rabbitmq,分布式,死信队列,TTL,死信交换机)