RabbitMQ
是等消息到达队列顶部即将被消费时,才会判断其是否过期并删除或者移至死信队列。所以即使消息过期,也不会马上从队列中抹去。
public class RabbitmqUtils {
private static Logger logger = LoggerFactory.getLogger(RabbitmqUtils.class);
// 死信相关队列
public static String NORMAL_EXCHANGE_NAME = "normal_exchange";
public static String NORMAL_EXCHANGE_ROUTING_KEY = "normal_routing_key";
public static String NORMAL_EXCHANGE_QUEUE_NAME = "normal_queue";
public static String DEAD_EXCHANGE_NAME = "dead_exchange";
public static String DEAD_EXCHANGE_QUEUE_NAME = "dead_queue";
public static String DEAD_EXCHANGE_ROUTING_KEY = "dead_routing_key";
// 队列持久化
public static boolean DURABLE = true;
public static Connection connection;
public static Channel channel;
static {
logger.info("getChannel begin...");
// 创建链接工厂
ConnectionFactory factory = new ConnectionFactory();
logger.info("getChannel factory:{}", factory.toString());
factory.setHost("192.168.6.8");
factory.setPort(5672);
factory.setUsername("admin");
factory.setPassword("123");
// 创建链接
try {
connection = factory.newConnection();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (TimeoutException e) {
throw new RuntimeException(e);
}
logger.info("getChannel connection:{}", connection.toString());
try {
channel = connection.createChannel();
} catch (IOException e) {
throw new RuntimeException(e);
}
logger.info("getChannel channel:{}", channel.toString());
logger.info("getChannel success!");
}
/**
* 死信队列实战
*
* @return
* @throws IOException
*/
public static Channel createDeadExchangeAndQueue() throws IOException {
// 删除已存在的交换机
channel.exchangeDelete(RabbitmqUtils.NORMAL_EXCHANGE_NAME);
channel.exchangeDelete(RabbitmqUtils.DEAD_EXCHANGE_NAME);
// 删除已存在的队列
channel.queueDelete(RabbitmqUtils.NORMAL_EXCHANGE_QUEUE_NAME);
channel.queueDelete(RabbitmqUtils.DEAD_EXCHANGE_QUEUE_NAME);
// 创建普通交换机
channel.exchangeDeclare(
RabbitmqUtils.NORMAL_EXCHANGE_NAME,
BuiltinExchangeType.DIRECT,
RabbitmqUtils.DURABLE);
// 正常队列绑定死信队列信息并设置队列的长度
HashMap arguments = new HashMap<>();
arguments.put("x-dead-letter-exchange",RabbitmqUtils.DEAD_EXCHANGE_NAME);
arguments.put("x-dead-letter-routing-key",RabbitmqUtils.DEAD_EXCHANGE_ROUTING_KEY);
arguments.put("x-max-length",6);
// 创建普通队列
channel.queueDeclare(
RabbitmqUtils.NORMAL_EXCHANGE_QUEUE_NAME,
RabbitmqUtils.DURABLE,
false,false,arguments);
// 将不同队列绑定到普通交换机上
channel.queueBind(
RabbitmqUtils.NORMAL_EXCHANGE_QUEUE_NAME,
RabbitmqUtils.NORMAL_EXCHANGE_NAME,
RabbitmqUtils.NORMAL_EXCHANGE_ROUTING_KEY);
// 创建死信交换机
channel.exchangeDeclare(
RabbitmqUtils.DEAD_EXCHANGE_NAME,
BuiltinExchangeType.DIRECT,
RabbitmqUtils.DURABLE);
// 创建死信队列
channel.queueDeclare(
RabbitmqUtils.DEAD_EXCHANGE_QUEUE_NAME,
RabbitmqUtils.DURABLE,
false,false,null);
// 将死信队列绑定到交换机上
channel.queueBind(
RabbitmqUtils.DEAD_EXCHANGE_QUEUE_NAME,
RabbitmqUtils.DEAD_EXCHANGE_NAME,
RabbitmqUtils.DEAD_EXCHANGE_ROUTING_KEY);
return channel;
}
}
public class DeadProducer {
private static Logger logger = LoggerFactory.getLogger(DeadProducer.class);
public static void main(String[] args) throws IOException {
Channel channel = RabbitmqUtils.createDeadExchangeAndQueue();
// 设置TTL过期
AMQP.BasicProperties properties = new AMQP.BasicProperties().builder().expiration("10000").build();
// 发送消息
String message2 = "info2";
channel.basicPublish(
RabbitmqUtils.NORMAL_EXCHANGE_NAME,
RabbitmqUtils.NORMAL_EXCHANGE_ROUTING_KEY,
properties,
message2.getBytes());
logger.info("发送的消息内容为:{}",message2);
}
}
刚发出去的结果:
过了10秒后的结果:
生产者代码:发送两个消息,将发送的第二条消息设置过期时间
public class DeadProducer {
private static Logger logger = LoggerFactory.getLogger(DeadProducer.class);
public static void main(String[] args) throws IOException {
Channel channel = RabbitmqUtils.createDeadExchangeAndQueue();
// 设置TTL过期
AMQP.BasicProperties properties = new AMQP.BasicProperties().builder().expiration("10000").build();
String message1 = "info1";
String message2 = "info2";
channel.basicPublish(
RabbitmqUtils.NORMAL_EXCHANGE_NAME,
RabbitmqUtils.NORMAL_EXCHANGE_ROUTING_KEY,
null,
message1.getBytes());
logger.info("发送的消息内容为:{}",message1);
channel.basicPublish(
RabbitmqUtils.NORMAL_EXCHANGE_NAME,
RabbitmqUtils.NORMAL_EXCHANGE_ROUTING_KEY,
properties,
message2.getBytes());
logger.info("发送的消息内容为:{}",message2);
}
}
结果如图:不管过去多长时间,第二条消息永远不会移至死信队列,因为判断过期时间在队列头部。因为消息1,没有被消费所以,队列判断不到消息2是否过期。