在业务开发中有时候会有这样的需求,例如 12306 购买车票,我们必须在30分钟内进行付款,如果超过30分钟,则该订单将会被自动取消。
要满足这个需求,可以采用 TTL 的这个特性功能。
我们先在管理页面操作一遍,然后再写代码案例。
创建队列同时设置 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>
“注意:如果执行队列发送消息报错,可以手动删除队列后,再重新创建队列解决 ”
<!-- 声明交换机 绑定 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>
/**
* 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过期时间。
还有另一种 消息单独过期 的功能,下面我们来继续实现。
## TTL:过期时间的设置有两种方式:
- 1. 队列统一过期
- 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;
}
};
// 发送消息: 设置单独过期
rabbitTemplate.convertAndSend("test_ttl_exchange", "ttl.hehe", "test ttl msg .......", messagePostProcessor);
}
此时虽然队列统一的过期时间为 100 秒,但是该消息的过期时间只有5秒,所以一会就消失了,如下:
5秒过后,立即消失:
此时会消失是因为该队列的消息只有一条,消息在顶端,如果消息不在顶端,那么则无法立即消失。
/**
* 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秒过后,才一起消失。
所以,单独设置消息的过期时间只有在被消费的时候才会进行判断是否过期,如果过期则立即丢弃。