DLX,全称为Dead-Letter-Exchange , 可以称之为死信交换机,也有人称之为死信邮箱。当消息在一个队列中变成死信(dead message)之后,它能被重新发送到另一个交换机中,这个交换机就是DLX ,绑定DLX的队列就称之为死信队列。
消息变成死信,可能是由于以下的原因:
DLX也是一个正常的交换机,和一般的交换机没有区别,它能在任何的队列上被指定,实际上就是设置某一个队列的属性。当这个队列中存在死信时,Rabbitmq就会自动地将这个消息重新发布到设置的DLX上去,进而被路由到另一个队列,即死信队列。
要想使用死信队列,只需要在定义队列的时候设置队列参数 x-dead-letter-exchange
指定交换机即可。
package com.sky.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* @author 尹稳健~
* @version 1.0
*/
@Configuration
public class TTLDirectRabbitMQConfig {
// 声明注册交换机
@Bean
public DirectExchange ttlDirectExchange(){
return new DirectExchange("ttl_direct_exchange");
}
// 声明队列
@Bean
public Queue ttlQueueDirect(){
Map<String,Object> args = new HashMap<>();
// 设置过期时间
args.put("x-message-ttl",5000);
// 设置死信队列
args.put("x-dead-letter-exchange","dead_direct_exchange");
// 设置 路由key
args.put("x-dead-letter-routing-key","dead");
return new Queue("ttl.direct.queue",true,false,false,args);
}
// 交换机和队列绑定
@Bean
public Binding ttlBindingDirect(){
return BindingBuilder.bind(ttlQueueDirect()).to(ttlDirectExchange()).with("ttl");
}
}
public void makeOrderTTL(String userId, String productId, int num) {
// 1:根据商品id查询库存是否充足
//2:保存订单
String orderId = UUID.randomUUID().toString();
System.out.println("订单生成成功"+orderId);
String exchangeName = "ttl_direct_exchange";
String routeKey = "ttl";
rabbitTemplate.convertAndSend(exchangeName,routeKey,orderId);
}
消息过期后转入死信交换机,然后通过死信交换机发送到死信队列中,其实死信交换机和其他的交换机没啥区别,也只是一个普普通通的交换机,不要把它想得很复杂,他只是一个回收站罢了。
- x-dead-letter-exchange 设置死信交换机
- x-dead-letter-routing-key 设置死信队列路由key
- x-message-ttl 设置过期时间
package com.sky.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* @author 尹稳健~
* @version 1.0
*/
@Configuration
public class TTLDirectRabbitMQConfig {
// 声明注册交换机
@Bean
public DirectExchange ttlDirectExchange(){
return new DirectExchange("ttl_direct_exchange");
}
// 声明队列
@Bean
public Queue maxQueueDirect(){
Map<String,Object> args = new HashMap<>();
// 设置过期时间
//args.put("x-message-ttl",5000);
// 设置队列最大数
args.put("x-max-length",3);
// 设置死信队列
args.put("x-dead-letter-exchange","dead_direct_exchange");
// 设置 路由key
args.put("x-dead-letter-routing-key","dead");
return new Queue("max.direct.queue",true,false,false,args);
}
// 交换机和队列绑定
@Bean
public Binding maxBindingDirect(){
return BindingBuilder.bind(maxQueueDirect()).to(ttlDirectExchange()).with("max");
}
}
public void makeOrderMax(String userId, String productId, int num) {
// 1:根据商品id查询库存是否充足
//2:保存订单
String orderId = UUID.randomUUID().toString();
System.out.println("订单生成成功"+orderId);
String exchangeName = "ttl_direct_exchange";
String routeKey = "max";
rabbitTemplate.convertAndSend(exchangeName,routeKey,orderId);
}
因为队列最大消息数设置为3条,我们测试一下队列达到最大数时,哪些消息会进入到死信队列中。
通过多次发送消息发现:当队列达到最大数时,继续发送消息,先前发送的消息会被丢弃到队列中,这就很像数据结构中的队列了,先进先出。