RabbitMQ死信队列DLX应用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RabbitMQ死信队列DLX应用相关的知识,希望对你有一定的参考价值。
参考技术A进入死信队列的场景:
运行 main 函数,推送消息给 TestDLXQueue 队列。可以先看到消息先在 TestDLXQueue 队列中。
等到30秒后没有被消费,则会把消息推送到 DLXQueue 死信队列中。
主要过程:
生产者 —> 原交换机 amq.direct —> 原队列 TestDLXQueue (超过 TTL 之后) —> 死信交换机 DLXExchange —> 死信队列 DLXQueue —> 最终消费者。
创建死信队列 DLX_QUEUE 并和指定交换机 DLX_EXCHANGE 进行绑定(其实也是普通的队列、普通的交换机)。
创建另外一个正常的消息队列 TEST_DLX_QUEUE ,设置队列的 TTL 过期时间,同时通过 x-dead-letter-exchange 属性指定死信队列对应的交换机。
等到30秒后没有被消费,则会把消息推送到 DLX_QUEUE 死信队列中。
所以在 RabbitMQ 3.5.8版本之后,可以利用官方的 rabbitmq-delayed-message-exchange 插件来实现消息的延迟发送,可以避免上面所说的问题。
RabbitMQ实现消息延迟推送
RabbitMQ 死信队列DLX
死信队列的简单介绍
利用dlx,当消息在一个队列中变成死信之后,它能被重新publish到另一个exchange,这个exchange就是dlx
消息变成死信的以下几种情况
消息被拒绝,并且requeue= false
消息ttl过期
队列达到最大的长度
dlx也是一个正常的exchange,和一般的exchange没什么区别,它能在任何的队列上被指定,实际上就是设置某个队列的属性。
当这个队列中有死信时,rabbitmq就会自动的将这个消息重新发布到设置的exchange上,进而被路由到另一个队列。
可以监听这个队列中消息做相应的处理,这个特性可以弥补rabbitMq3.0以前支持的immediate参数的功能。
消费端:
package com.flying.rabbitmq.api.dlx; import java.util.HashMap; import java.util.Map; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.QueueingConsumer; import com.rabbitmq.client.QueueingConsumer.Delivery; public class Consumer public static void main(String[] args) throws Exception ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.setHost("192.168.11.76"); connectionFactory.setPort(5672); connectionFactory.setVirtualHost("/"); Connection connection = connectionFactory.newConnection(); Channel channel = connection.createChannel(); // 这就是一个普通的交换机 和 队列 以及路由 String exchangeName = "test_dlx_exchange"; String routingKey = "dlx.#"; String queueName = "test_dlx_queue"; channel.exchangeDeclare(exchangeName, "topic", true, false, null); Map<String, Object> agruments = new HashMap<String, Object>(); agruments.put("x-dead-letter-exchange", "dlx.exchange"); //这个agruments属性,要设置到声明队列上 channel.queueDeclare(queueName, true, false, false, agruments); channel.queueBind(queueName, exchangeName, routingKey); //要进行死信队列的声明: channel.exchangeDeclare("dlx.exchange", "topic", true, false, null); channel.queueDeclare("dlx.queue", true, false, false, null); channel.queueBind("dlx.queue", "dlx.exchange", "#"); channel.basicConsume(queueName, true, new MyConsumer(channel));
自定义消费端:
package com.flying.rabbitmq.api.dlx; import java.io.IOException; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; public class MyConsumer extends DefaultConsumer public MyConsumer(Channel channel) super(channel); @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException System.err.println("-----------consume message----------"); System.err.println("consumerTag: " + consumerTag); System.err.println("envelope: " + envelope); System.err.println("properties: " + properties); System.err.println("body: " + new String(body));
生产端:
package com.flying.rabbitmq.api.dlx; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; public class Producer public static void main(String[] args) throws Exception ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.setHost("192.168.11.76"); connectionFactory.setPort(5672); connectionFactory.setVirtualHost("/"); Connection connection = connectionFactory.newConnection(); Channel channel = connection.createChannel(); String exchange = "test_dlx_exchange"; String routingKey = "dlx.save"; String msg = "Hello RabbitMQ DLX Message"; for(int i =0; i<1; i ++) AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder() .deliveryMode(2) .contentEncoding("UTF-8") .expiration("10000") .build(); channel.basicPublish(exchange, routingKey, true, properties, msg.getBytes());
以上是关于RabbitMQ死信队列DLX应用的主要内容,如果未能解决你的问题,请参考以下文章