RabbitMQ高级特性:TTL

125 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第22天,点击查看活动详情

RabbitMQ高级特性:TTL

什么是TTL?

TTL全程Time To Live(存活时间/过期时间)

当消息到达存活时间后,还没有被消费,会被自动清除

RabbitMQ可以对消息设置过期时间,也可以对整个队列(QUEUE)设置过期时间

比如我们下单一个商品,需要30分钟内支付,如果不支付订单就失效了,就算用到了这种技术

官网控制台实现TTL

单位为毫秒

x-message-ttl

最大存活时间

它有很多参数,这里我们先用第一个 最大存活时间

添加一个交换机

然后点进去我们创建的交换机 进行绑定队列

接下来进行消息发布

观察效果 10s后消息被清除

以上就算控制台实现TTL过期时间

代码实现TTL, 存活时间分为两种情况

在配置文件设置存活时间和相关参数

1 队列统一过期
 <? xml version="1.0" encoding="UTF-8" ?>

<beans xmlns="http://www.springframework.org/schema/beans"

 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 xmlns:context="http://www.springframework.org/schema/context"

 xmlns:rabbit="http://www.springframework.org/schema/rabbit"

 xsi:schemaLocation="http://www.springframework.org/schema/beans

 http://www.springframework.org/schema/beans/spring-beans.xsd

 http://www.springframework.org/schema/context

 https://www.springframework.org/schema/context/spring-context.xsd

 http://www.springframework.org/schema/rabbit

 http://www.springframework.org/schema/rabbit/spring-rabbit.xsd" >

    <!--加载配置文件-->

 <context:property-placeholder location="classpath:application.properties" />



    <!-- 定义rabbitmq connectionFactory -->

 <rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}"

 port="${rabbitmq.port}"

 username="${rabbitmq.username}"

 password="${rabbitmq.password}"

 virtual-host="${rabbitmq.virtual-host}"

 publisher-confirms="true"

 publisher-returns="true"



 />



    <!--定义管理交换机,队列-->

 <rabbit:admin connection-factory="connectionFactory" />



    <!--定义rabbitTemplate对象操作可以在代码中调用api发送消息-->

 <rabbit:template id="rabbitTemplate" connection-factory="connectionFactory" />



    <!--消息的可靠性投递(生产端)-->

 <!--队列-->

 <rabbit:queue id="test_queue_confirm" name="test_queue_confirm" ></rabbit:queue>

    <!--交换机 广播-->

 <rabbit:direct-exchange name="test_exchange_confirm" >

        <!--绑定queue-->

 <rabbit:bindings>

            <rabbit:binding queue="test_queue_confirm" key="confirm" ></rabbit:binding>

        </rabbit:bindings>

    </rabbit:direct-exchange>



    <!--ttl消息存活时间-->

 <!--声明队列queue-->

 <rabbit:queue name="test_queue_ttl" id="test_queue_ttl" >

            <!--设置queue队列存活时间-->

 <rabbit:queue-arguments>

            <!--通过entry设置属性 键值对应的格式 key=键 value=值 value-type表示值的数据类型-->



 <!--设置队列存活为10s 默认单位为毫秒

 由于存换时间是int类型 这边声明的是字符串 需要使用value-type表名值是整形的 不指定会报错的 -->

 <!--x-message-ttl 指队列的过期时间-->

 <entry key="x-message-ttl" value="10000" value-type="java.lang.Integer" ></entry>

      

        </rabbit:queue-arguments>

    </rabbit:queue>



    <!--声明交换机-->

 <rabbit:topic-exchange name="test_exchange_ttl" >

        <!--绑定交换机和队列-->

 <rabbit:bindings>

            <rabbit:binding pattern="ttl.#" queue="test_queue_ttl" ></rabbit:binding>

        </rabbit:bindings>

    </rabbit:topic-exchange>

</beans>


package com.producer.test;



import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.amqp.core.Message;

import org.springframework.amqp.rabbit.connection.CorrelationData;

import org.springframework.amqp.rabbit.core.RabbitTemplate;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;



 /**

 *  @prog ram: SpringBoot_RabbitMQ_Advanced

 *  @description:  测试确认模式消息是否发送成功

 *  @author:  魏一鹤

 *  @createDate:  2022-04-04 23:10

 **/



 //spring配置文件

@RunWith(SpringJUnit4ClassRunner.class)

 //加载文件的路径

@ContextConfiguration(locations = "classpath:spring-rabbitmq-producer.xml" )

public class ProducerTest {

    //注入 RabbitTemplate

 @Autowired

    private RabbitTemplate rabbitTemplate;





    //测试ttl

 /**

 *  ttl 过期时间分为两种

 *  1队列统一过期

 *  2消息单独过期

 **/

 @Test

    public void testTTL() {

        for (int i = 0; i < 10; i++) {

            //发送消息

  rabbitTemplate.convertAndSend( "test_exchange_ttl" , "ttl.weiyihe" , "message ttl..." );

        }

    }

}

2 消息单独过期


package com.producer.test;



import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.amqp.AmqpException;

import org.springframework.amqp.core.Message;

import org.springframework.amqp.core.MessagePostProcessor;

import org.springframework.amqp.rabbit.connection.CorrelationData;

import org.springframework.amqp.rabbit.core.RabbitTemplate;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;



 /**

 *  @prog ram: SpringBoot_RabbitMQ_Advanced

 *  @description:  测试确认模式消息是否发送成功

 *  @author:  魏一鹤

 *  @createDate:  2022-04-04 23:10

 **/



 //spring配置文件

@RunWith(SpringJUnit4ClassRunner.class)

 //加载文件的路径

@ContextConfiguration(locations = "classpath:spring-rabbitmq-producer.xml" )

public class ProducerTest {

    //注入 RabbitTemplate

 @Autowired

    private RabbitTemplate rabbitTemplate;



    //测试ttl

 /**

 *  ttl 过期时间分为两种

 *  1队列统一过期

 *  2消息单独过期

 *  如果设置了消息的过期时间,也设置了队列的过期时间,它以时间短的为准!

 *  如果队列过期后,会将队列所有消息全部移除,因为是统一的

 *  消息过期后,只有消息在队列顶端(快要被消费),才会判断其是否过期,如果过期就会被移除掉

 **/

 @Test

    public void testTTL() {

        //消息单独过期 在convertAndSend方法中心新增一个参数 MessagePostProcessor 加载匿名内部类和它的重写方法

 //MessagePostProcessor 消息处理对象 设置一些消息参数信息



 //发送消息

  for (int i = 0; i < 10; i++) {

            if(i==5){

                //处于消息顶端为快要消费的消息 过期的消息

  rabbitTemplate.convertAndSend( "test_exchange_ttl" , "ttl.weiyihe" , "message ttl..." ,new MessagePostProcessor(){

                    @Override

                    public Message postProcessMessage(Message message) throws AmqpException {

                        //设置message的信息  setExpiration 设置消息过期时间

 message.getMessageProperties().setExpiration( "10000" );

                        //返回该消息

  return message;

                    }

                });

            }else{

                //不过期的消息 正常的消息

  rabbitTemplate.convertAndSend( "test_exchange_ttl" , "ttl.weiyihe" , "message ttl..." );

            }

        }

    }

}

TTL小结

1 设置队列过期期间使用参数 x-message-ttl,单位(ms)毫秒,会对整个队列进行统一过期,丢弃掉队列中全部的消息
2 设置消息过期期间使用参数 expiration,单位(ms)毫秒,当该消息在队列头部时(在队列顶端说明快被消费了),会单独判断这一消息是否过期(是否被队列移除掉)
3 如果两者都进行了设置,以时间短的为准