
我是码农小胖哥,之前探讨了springboot 集成 rabbitmq 以及开启ack模式
传送门:10分钟就能轻松入门消息中间件rabbitmq(附带教学源码)
接着该搞一下死信队列了
- 业务场景
有时候 我们可能有些场景,不能让消费方那么快拿到消息。比如 10分钟后再告知对方消息。
还有如果消息超过一定时间没有消费我们把它转移到其他逻辑上去。
看过《让子弹飞》的都知道里面有句经典的台词:让子弹飞一会儿! 没错就是这个意思 ,让兔子再跑一会儿!

- 概念

死信队列 ,听上去像 消息“死”了, 其实也有点这个意思,死信队列是当消息在一个队列 因为下列原因:
- 消息被拒绝(basic.reject/ basic.nack)并且不再重新投递 requeue=false
- 消息超期 (rabbitmq Time-To-Live -> messageProperties.setExpiration())
- 队列超载
变成了 “死信” 后 ,被重新投递(publish)到另一个Exchange , 该Exchange 就是DLX , 然后该Exchange 根据绑定规则 转发到对应的某个队列上, 监听该队列就可以重新消费。, 说白了 就是 没有被消费的消息 换个地方重新被消费。流程大致如下:
生产者 --> 消息 --> 交换机 --> 队列 --> 变成死信 --> DLX交换机 -->队列 --> 消费者
- springboot rabbitmq 死信队列实践(认真看注释)
下面我们模拟一个死信队列的应用场景: 消息延时处理
还是以这个项目为基础: https://gitee.com/felord/springboot-message
项目中 RabbitConfig 死信相关片段:
/** * 死信队列跟交换机类型没有关系 不一定为directExchange 不影响该类型交换机的特性. * * @return the exchange */ @Bean("deadLetterExchange") public Exchange deadLetterExchange() { return ExchangeBuilder.directExchange("DL_EXCHANGE").durable(true).build(); } /** * 声明一个死信队列. * x-dead-letter-exchange 对应 死信交换机 * x-dead-letter-routing-key 对应 死信队列 * * @return the queue */ @Bean("deadLetterQueue") public Queue deadLetterQueue() { Map args = new HashMap<>(2);// x-dead-letter-exchange 声明 死信交换机 args.put(DEAD_LETTER_QUEUE_KEY, "DL_EXCHANGE");// x-dead-letter-routing-key 声明 死信路由键 args.put(DEAD_LETTER_ROUTING_KEY, "KEY_R"); return QueueBuilder.durable("DL_QUEUE").withArguments(args).build(); } /** * 定义死信队列转发队列. * * @return the queue */ @Bean("redirectQueue") public Queue redirectQueue() { return QueueBuilder.durable("REDIRECT_QUEUE").build(); } /** * 死信路由通过 DL_KEY 绑定键绑定到死信队列上. * * @return the binding */ @Bean public Binding deadLetterBinding() { return new Binding("DL_QUEUE