【README】死信队列是什么?
1)死信队列:当消息在一个队列中变成死信之后,它能被重新发送到另一个交换机中,这个交换机被称为DLX(Dead-Letter-Exchange-DLX , 死信交换机);绑定DLX的队列被称之为死信队列;
2)消息变成死信的原因有三个;
消息被拒绝;
消息过期;
队列达到最大长度;
【1】如何配置死信队列
1)首先死信队列是相对于正常业务队列而言的;
如 白条还款队列为业务队列, 当该队列有消息过期或被消费者拒绝或队列达到最大长度,则这些消息会被转发到私信队列; 又死信队列通常情况下通过 路由键进行转发,所以需要在死信队列前加一个交换机(俗称死信交换机);
2)要想使用死信队列,必须声明死信交换机,可以在声明正常业务队列的时候设置 正常业务队列对应的死信交换机(需要注意这个映射关系),如下:
/* 2-声明正常队列时,配置其对应死信队列 */
Map<String, Object> agruments = new HashMap<String, Object>();
agruments.put("x-dead-letter-exchange", DLX_EXCHANGE);
//这个agruments属性,要设置到声明队列上
channel.queueDeclare(NORM_QUEUE, true, false, false, agruments);
【2】死信队列荔枝
【2.1】 声明队列,交换机
step1)声明正常业务队列,正常业务交换机,定义正常业务路由键,以及三者间的绑定; 同时,在声明正常业务队列时,一定要设置其 死信交换机(DLX_EXCHANGE),作为属性传入声明方法;
step2)声明死信队列,死信交换机(DLX_EXCHANGE), 定义死信队列接收的路由键(#表示所有),以及三者间的绑定;
/**
* 声明正常队列+交换机;声明死信队列+交换机
*/
public class DlxDeclare {
public static final String POSTFIX = "_tr1";
/**
* 正常队列
*/
public static final String NORM_QUEUE = "norm_queue" + POSTFIX;
/**
* 正常交换机
*/
public static final String NORM_EXCHANGE = "norm_exchange" + POSTFIX;
/**
* 正常路由键
*/
public static final String NORM_ROUTE = "dlx.save" + POSTFIX;
/**
* 死信队列
*/
public static final String DLX_QUEUE = "dlx_queue" + POSTFIX;
/**
* 死信交换机
*/
public static final String DLX_EXCHANGE = "dlx_exchange" + POSTFIX;
/**
* 死信队列路由键-#-所有键
*/
public static final String DLX_ROUTE = "#";
public static void main(String[] args) throws Exception {
/* 获取连接*/
Connection conn = RBConnectionUtil.getConn();
// 创建信道
Channel channel = conn.createChannel();
/*1-声明正常交换机*/
channel.exchangeDeclare(NORM_EXCHANGE, BuiltinExchangeType.DIRECT);
/* 2-声明正常队列时,配置其对应死信队列 */
Map<String, Object> agruments = new HashMap<String, Object>();
agruments.put("x-dead-letter-exchange", DLX_EXCHANGE);
//这个agruments属性,要设置到声明队列上
channel.queueDeclare(NORM_QUEUE, true, false, false, agruments);
/* 3-绑定正常交换机,正常队列和路由键 */
channel.queueBind(NORM_QUEUE, NORM_EXCHANGE, NORM_ROUTE);
/*4-声明死信交换机,死信队列,并绑定两者*/
channel.exchangeDeclare(DLX_EXCHANGE, BuiltinExchangeType.TOPIC, true, false, null);
channel.queueDeclare(DLX_QUEUE, true, false, false, null);
channel.queueBind(DLX_QUEUE, DLX_EXCHANGE, DLX_ROUTE);
}
}
【2.2】生产者
1)我们把消息的 ttl 设置为10秒,即该消息10秒内没有被成功消费,则消息转发到死信队列;
/**
* 死信消息生产者
*/
public class DlxProducer {
public static void main(String[] args) throws Exception {
/* 获取连接*/
Connection conn = RBConnectionUtil.getConn();
// 创建信道
Channel channel = conn.createChannel();
AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
.expiration("10000") // 设置消息的ttl
.build();
/* 发送消息 */
long temp = System.currentTimeMillis();
for (int i = 1; i <= 20; i++) {
String msg = "我是 msg_norm消息,序号=" + (temp+i) + "时间=" + MyDateUtil.getNow();
channel.basicPublish(DlxDeclare.NORM_EXCHANGE, DlxDeclare.NORM_ROUTE, properties, msg.getBytes("UTF-8"));
System.out.println("生产者发送消息" + msg);
Thread.sleep(10);
}
/* 关闭连接和信道 */
channel.close();
conn.close();
}
}
【3】效果
1)生产者把消息发送到正常交换机 norm_exchange_tr1
2)10秒后,由于没有消费,消息被转发到死信队列 dlx_queue_tr1