RabbitMQ 死信队列的使用

死信队列

DLX 死信队列。有以下几种情况,消息会进入到死信队列中:

    消息过期 消息被拒绝 队列达到最大长度

实现的逻辑就是:也是创建一个交换机,就暂时叫它死信交换机,然后再创建一个死信队列,死信交换机和死信队列进行绑定。

当设置了ttl的队列中消息过期后就会把消息发送至我们的死信交换机,死信交换机再存入死信队列中,以后肯定还会有一个死信消费者来处理死信队列中的消息的。其实这还是一个提供者–>交换机—>队列---->消费者的过程。

问题是我们怎么让ttl队列过期后的消息发送至死信交换机中?

首先创建死信交换机、死信队列、绑定关系

/**
 * @author hs
 * @date 2021/06/29
 */
@Configuration
public class DeadConfiguration {
          
   

    @Bean
    public DirectExchange deadDirectExchange(){
          
   
        return new DirectExchange("dead_direct_exchange");
    }

    @Bean
    public Queue deadQueue(){
          
   
        return new Queue("dead.direct.queue",true);
    }

    @Bean
    public Binding deadBinding(){
          
   
        return BindingBuilder.bind(deadQueue()).to(deadDirectExchange()).with("dead");
    }
}

然后进行ttl队列和死信交换机进行绑定关系

@Bean
public Queue queueTtl(){
          
   
    //定义一个ttl队列
    //定义一个map集合存放参数
    Map<String,Object> arguments = new HashMap<>();
    // 这里的key参数需要从web图形化界面中获得
    arguments.put("x-message-ttl",5000);
    //设置死信交换机 map的key要从图形化界面获取  value是死信交换名
    arguments.put("x-dead-letter-exchange","dead_direct_exchange");
    // 因为我这个死信交换机采用的是direct模式 所有需要加一个路由key  但如果采用的是fanout模式 就不需要下面的语句
    arguments.put("x-dead-letter-routing-key","dead");
    return new Queue("ttl.direct.queue",true,false,false,arguments);
}

这里运行会报错,原因是这个设置了ttl的队列我之前就创建了,然后我刚刚有新增了两行代码加了些参数,该队列是不会及时变更的,需要删除ttl队列,然后再重新创建该队列。

但是在真实开发中,在线上高速运转时不能直接删除队列,需要重新改个名字,创建新ttl队列,把消息提供方改为新的队列,而不要直接去删除原来的队列。

现在再运行就会发现,ttl.direct.queue队列中的消息过了几秒就消失了,然后过了一会儿就出现在了dead.direct.queue队列中了。

上面也提到了队列超过能存放消息的最大长度后,消息也会转入死信队列。设置队列的最大长度如下所示: 代码的实现就只是在map集合中加一个这个参数x-max-length

经验分享 程序员 微信小程序 职场和发展