SpringBoot整合RabbitMQ(ttl+死信队列),定时消息

基于消息TTL与死信交换

死信交换: 可以为队列设置一个死信exchange和routingKey,当队列上产生死信时,死信会被投递到设置好的exchange及对应的routingKey,说白点就是可以为每个队列设置一个"回收站",产生死信就扔到回收站里,只不过回收站也是一个正常的队列.

消息成为死信的三中情况:

1.队列的消息长度达到限制
2.消费者拒接消费消息,basicNack/basicReject 并且不把消息重新放入原目标队列,requeue=false
3.原队列存在消息过期设置,消息到达超时时间未被消费
思路:

1.为消息设置过期时间

2.把消息投递到一个没有消费者的队列,ttl-queue 使消息成为死信

3.为ttl-queue设置死信交换,dead-letter-queue

4.为dead-letter-queue添加消费者,监听消息

引入rabbitMq 相关jar包

<!-- rabbitmq -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
            <version>2.4.4</version>
        </dependency>

先声明ttl 的交换机及队列;为没有消费者的队列,ttl-queue,绑定死信交换机,即为它指定"回收站"(死信交换)

@Configuration
public class TtlConfig {
    
    
    @Bean("myTtlExchange")
    public Exchange ttlExchange(){
    
    
        return new DirectExchange("mine-ttl-exchange");
    }

    @Bean("myTtlQueue")
    public Queue ttlQueue(){
    
    
        //设置在这个队列上的私信交换
        //mine-dead-letter-exchange 交换机
        //并且routingkey为mine.dead.letter
        Map<String,Object> args = new HashMap<>();
        args.put("x-dead-letter-exchange","mine-dead-letter-exchange");
        args.put("x-dead-letter-routing-key","mine.dead.letter");
        //过期时间由队列统一设置
        //注意不是 x-expires,x-expires为队列存活时间,
        // x-message-ttl为队列内的消息存活时间
        //注意更改队列/交换机设置需要删除原有的
//        args.put("x-message-ttl",20000);
        return new Queue("mine-ttl-queue",true,false,false,args);
    }

    @Bean
    @DependsOn({
    
    "myTtlExchange","myTtlQueue"})
    public Binding ttlBinding(Queue myTtlQueue, Exchange myTtlExchange){
    
    
        return BindingBuilder.bind(myTtlQueue).to(myTtlExchange).with("mine.ttl").noargs();
    }


}

监听上面设置好的死信队列

@Component
@RabbitListener(bindings = @QueueBinding(value = @Queue("mine-dead-letter-queue"),
        exchange = @Exchange("mine-dead-letter-exchange"),
        key = ("mine.dead.letter")))
public class DeadLetterListener {
    
    

    @RabbitHandler
    public void onMessage(String msg){
    
    
        System.out.println(msg);
        System.out.println(DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"));
    }
}

为消息设置过期时间

@GetMapping("testMq")
    public  void  testMq(){
    
    
        System.out.println(DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"));
        rabbitTemplate.convertAndSend("mine-ttl-exchange","mine.ttl","this is a rabbitmq test",message -> {
    
    
            //设置10秒的过期时间
            message.getMessageProperties().setExpiration("10000");
            return message;
        });
    }

温馨提醒:每条消息都设置过期时间,很灵活,若是固定的过期时间,可以在队列上设置, 为队列设置 x-message-ttl 那在这个队列上的每条消息的过期时间都为 x-message-ttl 的值,如下面所示:

@Bean("myTtlQueue")
    public Queue ttlQueue(){
    
    
        //设置在这个队列上的私信交换(垃圾桶)
        //mine-dead-letter-exchange 交换机
        //并且routingkey为mine.dead.letter
        Map<String,Object> args = new HashMap<>();
        args.put("x-dead-letter-exchange","mine-dead-letter-exchange");
        args.put("x-dead-letter-routing-key","mine.dead.letter");
        //过期时间由队列统一设置
        //注意不是 x-expires,x-expires为队列存活时间,
        // x-message-ttl为队列内的消息存活时间
        //注意更改队列/交换机设置需要删除原有的
       args.put("x-message-ttl",20000);
        return new Queue("mine-ttl-queue",true,false,false,args);
    }

另:基于插件 RabbitMQ Delayed Message Plugin 个人推荐这篇文章 有兴趣的可以了解下https://blog.csdn.net/gw5205566/article/details/104594866

猜你喜欢

转载自blog.csdn.net/weixin_45818787/article/details/116013918