分享

14-RabbitMQ高级特性-TTL

 邸彦强 2023-06-01 发布于河北

前言

在业务开发中有时候会有这样的需求,例如 12306 购买车票,我们必须在30分钟内进行付款,如果超过30分钟,则该订单将会被自动取消。

要满足这个需求,可以采用 TTL 的这个特性功能。

图片

TTL

  • TTL 全称 Time To Live(存活时间/过期时间)。
  • 当消息到达存活时间后,还没有被消费,会被自动清除。
  • RabbitMQ可以对消息设置过期时间,也可以对整个队列(Queue)设置过期时间。

管理页面 操作发送 TTL消息

我们先在管理页面操作一遍,然后再写代码案例。

1.创建队列

创建队列同时设置 TTL 参数。

图片
图片

2.创建交换机

图片

3.绑定交换机与队列

图片

创建好交换机之后,点进去交换机绑定队列:

图片
图片

4.发送消息

图片
图片

5.在队列查看 TTL 消息

一开始进入队列是可以看到消息的,等待几秒后,消息自动消失了。

图片
图片

代码演示

在上面我们已经在管理页面演示了一遍,下面我们在代码里面进行演示。

1.项目工程

打开我们之前演示消息可靠性的生产者工程:

图片

2.配置 队列统一过期 TTL

图片
    <!--ttl-->
    <rabbit:queue name='test_ttl_queue' id='test_ttl_queue'>
        <!--设置queue的参数-->
        <rabbit:queue-arguments>
            <!--x-message-ttl指队列的过期时间,单位毫秒-->
            <entry key='x-message-ttl' value='100000' value-type='java.lang.Integer'></entry>
        </rabbit:queue-arguments>
    </rabbit:queue>

注意:如果执行队列发送消息报错,可以手动删除队列后,再重新创建队列解决

3.声明交换机 以及 绑定队列

图片
<!-- 声明交换机 绑定 ttl 队列   -->
<rabbit:topic-exchange name='test_ttl_exchange' >
    <rabbit:bindings>
        <rabbit:binding pattern='ttl.#' queue='test_ttl_queue'></rabbit:binding>
    </rabbit:bindings>
</rabbit:topic-exchange>

4. 编写发送队列消息,查看消息是否自动过期消失

图片
/**
 * TTL:过期时间
 *  1. 队列统一过期
 *  2. 消息单独过期
 *
 * 如果设置了消息的过期时间,也设置了队列的过期时间,它以时间短的为准。
 * 队列过期后,会将队列所有消息全部移除。
 * 消息过期后,只有消息在队列顶端,才会判断其是否过期(移除掉)
 */

@Test
public void testTTL() {

    // 发送消息
    for (int i = 0; i < 10; i++) {
        rabbitTemplate.convertAndSend('test_ttl_exchange''ttl.hehe''test ttl msg .......');
        System.out.println('发送消息: test ttl msg .......' + i);
    }

}

在管理页面查看队列中的消息:

图片

等待一会再看队列的消息,可以看到自动清零了,如下:

图片

那么这里我们就实现了队列统一配置的TTL过期时间。

还有另一种 消息单独过期 的功能,下面我们来继续实现。

5. 消息单独过期

## TTL:过期时间的设置有两种方式:
1. 队列统一过期
2. 消息单独过期
 
## 注意:
> 如果设置了消息的过期时间,也设置了队列的过期时间,它以时间短的为准。
 队列过期后,会将队列所有消息全部移除。
 消息过期后,只有消息在队列顶端,才会判断其是否过期(移除掉)

5.1 编写消息单独过期

图片
/**
     * TTL:过期时间
     *  1. 队列统一过期
     *  2. 消息单独过期
     *
     * 如果设置了消息的过期时间,也设置了队列的过期时间,它以时间短的为准。
     * 队列过期后,会将队列所有消息全部移除。
     * 消息过期后,只有消息在队列顶端,才会判断其是否过期(移除掉)
     */

    @Test
    public void testTTL() {
        
        // 消息后处理对象,设置一些消息的参数信息
        MessagePostProcessor messagePostProcessor = new MessagePostProcessor(){

            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                // 设置message的属性
                message.getMessageProperties().setExpiration('5000');// 设置消息过期时间5秒
                // 返回该消息
                return message;
            }
        };


        // 发送消息: 设置单独过期
        rabbitTemplate.convertAndSend('test_ttl_exchange''ttl.hehe''test ttl msg .......', messagePostProcessor);


    }

此时虽然队列统一的过期时间为 100 秒,但是该消息的过期时间只有5秒,所以一会就消失了,如下:

图片

5秒过后,立即消失:

图片

此时会消失是因为该队列的消息只有一条,消息在顶端,如果消息不在顶端,那么则无法立即消失。

5.2 验证消息在中间位置,不会立即消失

图片
/**
 * TTL:过期时间
 *  1. 队列统一过期
 *  2. 消息单独过期
 *
 * 如果设置了消息的过期时间,也设置了队列的过期时间,它以时间短的为准。
 * 队列过期后,会将队列所有消息全部移除。
 * 消息过期后,只有消息在队列顶端,才会判断其是否过期(移除掉)
 */

@Test
public void testTTL() {

    // 消息后处理对象,设置一些消息的参数信息
    MessagePostProcessor messagePostProcessor = new MessagePostProcessor(){

        @Override
        public Message postProcessMessage(Message message) throws AmqpException {
            // 设置message的属性
            message.getMessageProperties().setExpiration('5000');// 设置消息过期时间5秒
            // 返回该消息
            return message;
        }
    };

    // 发送消息
    for (int i = 0; i < 10; i++) {

        if (i == 5) {
            // 发送消息: 设置单独过期 5秒
            rabbitTemplate.convertAndSend('test_ttl_exchange''ttl.hehe''test ttl msg .......', messagePostProcessor);
        } else {
            // 发送消息: 基于队列统一过期时间 100秒
            rabbitTemplate.convertAndSend('test_ttl_exchange''ttl.hehe''test ttl msg .......');
        }
        System.out.println('发送消息: test ttl msg .......' + i);

    }

}

执行之后,我们再来查看队列的信息:

图片

经过观察可以发现 5秒过后,消息队列依然还是10条消息,统一到了100秒过后,才一起消失。

所以,单独设置消息的过期时间只有在被消费的时候才会进行判断是否过期,如果过期则立即丢弃。

小结

  • 设置队列过期时间使用参数:x-message-ttl,单位:ms(毫秒),会对整个队列消息统一过期。
  • 设置消息过期时间使用参数:expiration。单位:ms(毫秒),当该消息在队列头部时(消费时),会单独判断这一消息是否过期。
  • 如果两者都进行了设置,以时间短的为准。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多