RabbitMQ-死信队列-过期了的消息为什么不自动进入死信队列?

结论:

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);

    }
}

刚发出去的结果:

RabbitMQ-死信队列-过期了的消息为什么不自动进入死信队列?_第1张图片

 过了10秒后的结果:

RabbitMQ-死信队列-过期了的消息为什么不自动进入死信队列?_第2张图片

 生产者代码:发送两个消息,将发送的第二条消息设置过期时间

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是否过期。

RabbitMQ-死信队列-过期了的消息为什么不自动进入死信队列?_第3张图片

 

你可能感兴趣的:(RabbitMQ,java-rabbitmq,rabbitmq,java)