RabbitMQ 高级特性——延迟队列

在这里插入图片描述

前言

前面我们学习了 TTL 和死信队列,当队列中的消息达到了过期时间之后,那么这个消息就会被死信交换机投递到死信队列中,然后由专门的消费者进行消费,这篇文章将为大家介绍 RabbitMQ 的另一高级特性——延迟队列。

延迟队列

延迟队列的概念

延迟队列通常指的是一种队列,其中的消息在发送后不会立即被消费,而是会等待一段时间(即延迟时间)后才变得可消费。

RabbitMQ 本身不直接提供名为“延迟队列”的内置功能,但我们可以利用 RabbitMQ 的一些特性和机制来模拟或实现延迟队列的行为。就比如 TTL + 死信队列方式模拟出延迟队列的功能。

TTL + 死信队列模拟延迟队列

在这里插入图片描述

我们的消费者不去消费正常队列中的消息,而是去消费死信队列中的消息,为什么这样能实现延迟对立的功能呢?当生产者生产消息投递给正常交换机之后,交换机会将这个消息根据 routing key 和 binding key 路由到指定的队列中,因为这个正常队列没有消费者可以消费消息,所以到达了了这个队列中的消息,就会存储在这个队列中,因为这个队列设置了 TTL,所以消息到达了过期时间之后就会被投递给死信交换机 DLX,然后死信交换机就会将这个消息投递给 DLQ,然后消费者从这个 DLQ 中去消费消息,这样消费者就会在生产者生产的消息到达队列之后不会立即去消费,而是会等待一段时间,这样就通过 TTL + 死信队列的方式模拟出了延迟队列的功能。

设置队列的 TTL

那么我们看看通过代码如何实现:

public class Constants {
   
    
    
    public static final String NORMAL_EXCHANGE = "normal.exchange";
    public static final String NORMAL_QUEUE = "normal.queue";
    public static final String DL_EXCHANGE = "dl.exchange";
    public static final String DL_QUEUE = "dl.queue";
}

声明交换机、队列和绑定关系:

@Configuration
public class DLConfig {
   
    
    
    @Bean("normalExchange")
    public Exchange normalExchange() {
   
    
    
        return ExchangeBuilder.directExchange(Constants.NORMAL_EXCHANGE).build();
    }

    @Bean("normalQueue")
    public Queue normalQueue() {
   
    
    
        return QueueBuilder.durable(Constants.NORMAL_QUEUE)
                .ttl(1000)
                .deadLetterExchange(Constants.DL_EXCHANGE)
                .deadLetterRoutingKey("dl")
                .build();
    }

    @Bean("normalBinding")
    public Binding normalBinding(@Qualifier("normalExchange") Exchange exchange, @Qualifier("normalQueue") Queue queue) {
   
    
    
        return BindingBuilder.bind(queue).to(exchange).with("normal").noargs();
    }

    @Bean("DLExchange")
    public Exchange DLExchange() {
   
    
    
        return ExchangeBuilder.directExchange(Constants.DL_EXCHANGE).build();
    }

    @Bean("DLQueue")
    public Queue