概述
过期时间TTL表示可以对消息设置预期的时间,在这个时间内都可以被消费者接收获取;过了之后消息将自动被删除。RabbitMQ可以对消息和队列设置TTL。目前有两种方法可以设置。
- 第一种方法是通过队列属性设置,队列中所有消息都有相同的过期时间。
- 第二种方法是对消息进行单独设置,每条消息TTL可以不同。
如果上述两种方法同时使用,则消息的过期时间以两者之间TTL较小的那个数值为准。消息在队列的生存时间一旦超过设置的TTL值,就称为dead message被投递到死信队列, 消费者将无法再收到该消息。
1、设置队列TTL
1、创建exchange 和 queue,并且绑定
package com.sky.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* @author 尹稳健~
* @version 1.0
*/
@Configuration
public class TTLDirectRabbitMQConfig {
// 声明注册交换机
@Bean
public DirectExchange ttlDirectExchange(){
return new DirectExchange("ttl_direct_exchange");
}
// 声明队列
@Bean
public Queue ttlQueueDirect(){
Map<String,Object> args = new HashMap<>();
// 设置过期时间
args.put("x-message-ttl",5000);
return new Queue("ttl.direct.queue",true,false,false,args);
}
// 交换机和队列绑定
@Bean
public Binding ttlBindingDirect(){
return BindingBuilder.bind(ttlQueueDirect()).to(ttlDirectExchange()).with("ttl");
}
}
2、发送消息
public void makeOrderTTL(String userId, String productId, int num) {
// 1:根据商品id查询库存是否充足
//2:保存订单
String orderId = UUID.randomUUID().toString();
System.out.println("订单生成成功"+orderId);
String exchangeName = "ttl_direct_exchange";
String routeKey = "ttl";
rabbitTemplate.convertAndSend(exchangeName,routeKey,orderId);
}
3、测试
一开始有一条信息进入队列但是过5s就消失了。那他去哪了呢?注意那几个蓝色的图标DLX 代表死信队列交换机
DLK代表私信队列的路由key,过期消息会进入到死信队列中,这个是需要自己去设置的,我们后面会说。
2、设置消息TTL
1、创建交换机和队列,并且绑定
package com.sky.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* @author 尹稳健~
* @version 1.0
*/
@Configuration
public class TTLDirectRabbitMQConfig {
// 声明注册交换机
@Bean
public DirectExchange ttlDirectExchange(){
return new DirectExchange("ttl_direct_exchange");
}
// 声明队列
@Bean
public Queue ttlMessageQueueDirect(){
return new Queue("ttl.message.direct.queue",true);
}
// 交换机和队列绑定
@Bean
public Binding ttlMessageBindingDirect(){
return BindingBuilder.bind(ttlMessageQueueDirect()).to(ttlDirectExchange()).with("ttlMessage");
}
}
2、发送消息
public void makeOrderTTLMessage(String userId, String productId, int num) {
// 1:根据商品id查询库存是否充足
//2:保存订单
String orderId = UUID.randomUUID().toString();
System.out.println("订单生成成功"+orderId);
//3:通过MQ来完成消息的分发
// 参数1 : 交换机 参数2:路由key / 队列名称 参数3 :消息内容
String exchangeName = "ttl_direct_exchange";
String routeKey = "ttlMessage";
// 给消息设置过期时间
MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setExpiration("5000");
message.getMessageProperties().setContentEncoding("UTF-8");
return message;
}
};
rabbitTemplate.convertAndSend(exchangeName,routeKey,orderId,messagePostProcessor);
}
测试
小结
- 设置过期时间的队列的信息是RabbitMQ删除的,不是我手动删除的!
- 过期时间是要自己手动设置的 参数key是x-message-ttl