RabbitMQ之死信队列

Posted 朱小厮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RabbitMQ之死信队列相关的知识,希望对你有一定的参考价值。


欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。

欢迎跳转到本文的原文链接:https://honeypps.com/mq/rabbitmq-analysis-of-dlx/

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);

你也可以为这个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

欢迎跳转到本文的原文链接:https://honeypps.com/mq/rabbitmq-analysis-of-dlx/


参考资料

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

欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。

以上是关于RabbitMQ之死信队列的主要内容,如果未能解决你的问题,请参考以下文章

RabbitMQ项目使用之死信队列

RabbitMQ项目使用之死信队列

RabbitMq高级特性之死信队列 通俗易懂 超详细 内含案例

springBoot集成rabbitmq 之延时(死信)队列

SpringBoot集成RabbitMQ之死信队列限流队列延迟队列(第四节)

RabbitMQ之消息可靠性死信交换机惰性队列及集群