开启掘金成长之旅!这是我参与「掘金日新计划 · 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..." );
}
}
}
}