死信队列:当消息在一个队列中变成死信之后,它能被重新pushlish到另一个exchange,这个exchange就是死信队列(DXL)。
消息变成死信几种情况:
- 消息被拒绝nack,并且requeue=false不重回队列
- 消息TTL过期
- 队列达到最大长度
死信队列其实也是一个正常exchange,也是需要和队列绑定使用。只是其他队列在发生死信的时候,可以指定死信消息重新push到达这个死信exchange。
给一个正常业务队列,设置它的死信队列方式,是在声明queue的时候在arguments参数里设置x-dead-letter-exchange属性,x-dead-letter-exchange这个key对应的value就是你已经声明好,要用来做死信队列的exchange。例如:queueArgument.put("x-dead-letter-exchange","dxl_test_exchange");
使用:
- 声明死信的exchange和queue并做绑定(和声明普通交换机exchange一样)
- 声明主业务的exchange和queue,并给queue绑定上面声明的死信队列
- 当主业务队列消息满足变成上面讲的三种死信的条件一种时候,信息会repush到死信交换机,然后到达死信queue
代码测试:
生产端
package com.vivo.demo1.ttl;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;
/**
* @author:luzaichun
* @Date:2020/12/27
* @Time:19:14
**/
public class Producer {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.3.8");
factory.setPort(5672);
factory.setVirtualHost("/");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
//1.声明死信队列
channel.exchangeDeclare("dlx.exchange","topic",false,false,null);
channel.queueDeclare("dlx.queue",false,false,false,null);
channel.queueBind("dlx.queue","dlx.exchange","#");
//2.声明主业务交换机,队列,及绑定关系
//设置业务队列的arguments,绑定它的死信队列
Map<String, Object> queueArgument = new HashMap<>();
queueArgument.put("x-dead-letter-exchange","dlx.exchange");
channel.exchangeDeclare("test_exchange","topic",false,false,null);
channel.queueDeclare("test_queue",false,false,false,queueArgument);
channel.queueBind("test_queue","test_exchange","topic.#",null);
//3.设置消息的properties,设置5秒过期,用于演示ttl后消息repush到绑定的死信队列
AMQP.BasicProperties basicProperties = new AMQP.BasicProperties().builder()
//从消息的维度设置过期时间
.expiration("5000")
.build();
//4.发送消息
channel.basicPublish("test_exchange", "topic.test.dlx", basicProperties, "这是一个ttl消息,用于测试dlx".getBytes());
System.out.println("============================");
channel.close();
connection.close();
}
}
我们能观察到,消息最开始在test_queue队列,当消息ttl过期后(本例中5000毫秒),消息会流转到死信dlx.queue中。