# 过期时间

RabbitMQ 有两种方式可以设置消息的过期时间。第一种是通过队列属性设置,队列中所有的信息都有相同的过期时间,第二种方式是对消息本身进行单独设置,每条消息的 TTL 可以不同。** 如果两种方式一起中,则消息的 TTL 以两者之间较短的那个数值为准。** 消息在队列中的生存时间,一旦超过设置的 TTL 时,就会变成 “死信”。

# springboot 中设置消息 TTL 的方式

# 设置队列属性

@Bean
    public Queue ttlQueue() {
        Map<String, Object> param = new HashMap<>();
        param.put("x-message-ttl", 1000 * 20);
        return new Queue("ttl-queue", true, false, false, param);
    }

这样就声明了一个带有 20 秒过期时间的队列,将它与交换机进行绑定,就能实现过期时间功能。

# 消息单独设置过期时间

@Test
    public void testMQ() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            MessagePostProcessor messagePostProcessor =new MessagePostProcessor() {
                @Override
                public Message postProcessMessage(Message message) throws AmqpException {
                    message.getMessageProperties().setExpiration("10000");
                    return message;
                }
            };
            rabbitTemplate.convertAndSend("config_exchange2", "kkk", "发送消息" + i,messagePostProcessor,new CorrelationData(String.valueOf(i)));
        }      
    }
}

如果为单独消息设置过期时间,需要编写 MessagePostProcesssor 中的 message 的 expiration 属性进行设置,注意过期时间要用字符串表示。

# 两种方式的区别

除了可以单独设置过期时间以外,第一种设置队列过期时间的方式,一旦消息过期,就会从队列中抹去,第二种方法,即使消息过期,也不会立刻从队列中抹去,而是每条消息是否过期时在即将投递到消费者之前进行判断的。

# 死信队列

DLX,全称为 Dead-Letter-Exchange,死信交换机,当消息在一个队列中变成死信之后,它能被重新发送到死信交换机中,绑定了死信交换机的就是死信队列。

# 消息变成死信的情况

  • 消息被拒绝,并且设置 requeue 参数为 false;
  • 消息过期
  • 队列达到最大长度。

# springboot 设置死信队列

DLX 也是一个正常的交换机,和一般的交换机没有区别,死信队列可以在任何队列上被指定,实际上就是给队列设置一个死信交换机的属性。当这个队列中有死信时,rabbitMQ 就会把消息重新发送给设置的 DLX 中。

1、声明队列和死信交换机并进行绑定
 @Bean
    public TopicExchange DLX() {
        TopicExchange topicExchange = new TopicExchange("DLX", true, false);
        return topicExchange;
    }
    @Bean
    public Queue DLQ(){
        return new Queue("DLQ",true,false,false);
    }
    @Bean
    public Binding DLXBinding(){
        return BindingBuilder.bind(DLQ()).to(DLX()).with("*.b.*");
    }
2、给队列指定死信交换机
 @Bean
    public Queue ttlQueue() {
        Map<String, Object> param = new HashMap<>();
        param.put("x-message-ttl", 10000);
        param.put("x-dead-letter-exchange", "DLX");
        return new Queue("ttl-queue", true, false, false, param);
    }

整体设置死信队列的逻辑就是:

  • 声明一个新的队列
  • 声明一个新的交换机(作为死信交换机,为了能够成功将消息路由给死信队列,要保持交换机类型和要绑定的交换机相同,例如 A 是 Topic 类型的交换机,那么作为 A 的队列的死信交换机,也要用 Topic 类型)
  • 完成交换机和队列之间的绑定(这里要注意路由键的问题,保证路由键和原来的相同,这样才能正常的将死信路由过来)
  • 给原来的交换机绑定的队列配置死信交换机,命令是 "x-dead-letter-exchange", “死信交换机名称”