⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 blog.csdn.net/u013256816/article/details/54933065 「朱小厮」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

DLX, Dead-Letter-Exchange。利用DLX, 当消息在一个队列中变成死信(dead message)之后,它能被重新publish到另一个Exchange,这个Exchange就是DLX。消息变成死信一向有一下几种情况:

DLX也是一个正常的Exchange,和一般的Exchange没有区别,它能在任何的队列上被指定,实际上就是设置某个队列的属性,当这个队列中有死信时,RabbitMQ就会自动的将这个消息重新发布到设置的Exchange上去,进而被路由到另一个队列,可以监听这个队列中消息做相应的处理,这个特性可以弥补RabbitMQ 3.0以前支持的immediate参数(可以参考RabbitMQ之mandatory和immediate)的功能。

核心代码实现:通过在queueDeclare方法中加入“x-dead-letter-exchange”实现。

channel.exchangeDeclare("some.exchange.name", "direct");

Map<String, Object> args = new HashMap<String, Object>();
args.put("x-dead-letter-exchange", "some.exchange.name");
channel.queueDeclare("myqueue", false, false, false, args);
12345

你也可以为这个DLX指定routing key,如果没有特殊指定,则使用原队列的routing key

args.put("x-dead-letter-routing-key", "some-routing-key");

还可以使用policy来配置:

rabbitmqctl set_policy DLX ".*" '{"dead-letter-exchange":"my-dlx"}' --apply-to queues

修改RabbitMQ之TTL(Time-To-Live 过期时间)中的例子:

public static void createQueue(){
try {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(ip);
factory.setPort(port);
factory.setUsername(username);
factory.setPassword(password);

Connection connection = factory.newConnection();
Channel channel = connection.createChannel();

Map<String, Object> argss = new HashMap<String, Object>();
argss.put("vhost", "/");
argss.put("username","root");
argss.put("password", "root");
argss.put("x-message-ttl",6000);
argss.put("x-dead-letter-exchange","exchange.dlx.test");
argss.put("x-dead-letter-routing-key","queue.dlx.test");
channel.queueDeclare("queue.dlx.test", durable, exclusive, autoDelete, argss);
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}

通过RabbitMQ的管理界面可以看到: 这里写图片描述 queue.dlx.test这个queue中有个“DLX"和“DLK”的标记. DLX关联的是exchangeName, DLK关联的是routingKey.

详细说明: 在RabbitMQ中有两个exchange: exchange.dlx.self和exchange.dlx.test,两个queue:queue.dlx.test和%DLX%queue.dlx.test exchange.dlx.self是正常情况下,生产者发送消息到此exchange中,绑定关系如图: 这里写图片描述 exchang.dlx.test是产生死信之后,原queue[queue.dlx.test]的死信发送到此exchange中,绑定关系如图: 这里写图片描述

数据首先发送到 exchange[exchange.dlx.self],根据routingkey[dlx]路由到queue.dlx.test,如果正常情况下,消费者可以消费queue.dlx.test的内容。但是如果queue.dlx.test中有消息变成了dead message即死信了,那么这个死信则会通过exchangeName=exchange.dlx.test, routingKey="queue.dlx.test"路由到死信队列%DLX%queue.dlx.test中,如果要消费这个dead message, 此时消费者必须消费%DLX%queue.dlx.test中的内容而不是queue.dlx.test中的内容。

如果不指定x-dead-letter-routing-key参数,则使用原来的routingkey

参考资料

  1. RabbitMQ之TTL(Time-To-Live 过期时间)
  2. RabbitMQ之mandatory和immediate
  3. RabbitMQ(四)RabbitMQ死信邮箱(DLX)
  4. RabbitMQ Dead Letter Exchanges
文章目录