DLX:死信队列 DEAD-LETTER_EXCHANGE,也可以称之为死信交换机,当消息在一个队列中变为过期的死信(DEAD_MESSAGE)之后,它可以被重新发送到另一个交换机中,这个交换即就是死信交换机,绑定死信交换机的队列就是死信队列而消息变成死信的原因可以有以下几种

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

想要使用死信队列,只需要在定义队列的时候定义参数即可
x-dead-letter-exchange 并指定交换机即可

image.png

消息过长转移到死信队列

配置类

定义一个死信交换机和死信队列

  1. @Configuration
  2. public class DeadRabbitConfig {
  3. // 声明注册direct模式的交换机
  4. @Bean
  5. public DirectExchange deadExchange() {
  6. return new DirectExchange("dead_direct_exchange", true, false);
  7. }
  8. // 设置死信队列
  9. @Bean
  10. public Queue deadQueue() {
  11. return new Queue("dead_direct_queue", true);
  12. }
  13. @Bean
  14. public Binding deadBinding() {
  15. return BindingBuilder.bind(deadQueue()).to(deadExchange()).with("dead_direct_message");
  16. }
  17. }

将正常的交换机和死信交换机进行绑定

  1. @Configuration
  2. public class TTLRabbitConfig {
  3. // 声明注册direct模式的交换机
  4. @Bean
  5. public DirectExchange ttlDirectExchange() {
  6. return new DirectExchange("ttl_direct_exchange", true, false);
  7. }
  8. @Bean
  9. public DirectExchange ttlMessageDirectExchange() {
  10. return new DirectExchange("ttl_message_direct_exchange", true, false);
  11. }
  12. // 设置队列过期时间
  13. @Bean
  14. public Queue ttlQueue() {
  15. //设置队列参数
  16. Map<String, Object> args = new HashMap<>();
  17. //x-message-ttl: 表示过期时间
  18. args.put("x-message-ttl", 5000);
  19. //绑定死信交换机
  20. args.put("x-dead-letter-exchange","dead_direct_exchange");
  21. //绑定死信key direct模式下需要配置
  22. args.put("x-dead-letter-routing-key","dead");
  23. return new Queue("ttl_direct_queue", true, false, false, args);
  24. }
  25. // 设置消息过期时间
  26. @Bean
  27. public Queue ttlMessageQueue() {
  28. return new Queue("ttl_message_direct_queue", true);
  29. }
  30. // 完成交换机和队列,路由key的绑定
  31. @Bean
  32. public Binding ttlBinding() {
  33. return BindingBuilder.bind(ttlQueue()).to(ttlDirectExchange()).with("ttl");
  34. }
  35. @Bean
  36. public Binding ttlMessageBinding() {
  37. return BindingBuilder.bind(ttlMessageQueue()).to(ttlMessageDirectExchange()).with("ttL_message");
  38. }
  39. }

如果是direct模式下,绑定死信交换机的同时还需要绑定死信队列的路由key,fanout模式不需要

image.png

测试类

  1. public boolean ttlDirectOrder(String userId, String productId, Integer num) {
  2. //保存订单业务执行
  3. String orderId = UUID.randomUUID().toString();
  4. log.info("订单业务执行完毕");
  5. log.info("开始异步执行消息分发");
  6. //通过MQ进行消息分发
  7. //定义交换机
  8. String exchangeName = "ttl_direct_exchange";
  9. //消息分发
  10. rabbitTemplate.convertAndSend(exchangeName, "ttl", orderId);
  11. return false;
  12. }

测试结果

image.png

死信队列作为消息队列的一种可靠机制

消息过长

配置类

  1. // 设置队列过期时间
  2. @Bean
  3. public Queue ttlQueue() {
  4. //设置队列参数
  5. Map<String, Object> args = new HashMap<>();
  6. //x-message-ttl: 表示过期时间
  7. args.put("x-message-ttl", 5000);
  8. //队列容纳最大长度
  9. args.put("x-max-length", 5);
  10. //绑定死信交换机
  11. args.put("x-dead-letter-exchange","dead_direct_exchange");
  12. //绑定死信key direct模式下需要配置
  13. args.put("x-dead-letter-routing-key","dead");
  14. return new Queue("ttl_direct_queue", true, false, false, args);
  15. }

结果

队列只能容纳5条消息,多余的会转移到死信队列