在开发场景中,如预约的签到,用户会有不同的预约签到时间,例如;7:00,7:30,8:00
那么,对于这种场景,使用如定点轮询查表的方式,一方面时间颗粒度需要严格的控制,另一方面在数据库的记录一多就很浪费性能,所以我们可以考虑使用mq的过期队列来实现功能
基于mq的死信队列,首先将信息存活时间设置为 "从当前时间到需要的判断的截止时间" -> "在项目中编写方法监听死信队列" 这样就是一个动态设置的理论基础,ok,理论形成,我们来看看在配置,和一些小部分的细节
配置上,首先你需要 一个正常的交换机,一个正常的队列,将队列绑定到对应的交换机上,同时定义一个死信交换机和死信队列,同样先将死信队列绑定上死信队列,最后一定记得把死信队列绑定上正常的交换机 (以上就是理论的配置流程 至于路由键的设置就更具实际情况来设置并不是强制需要的配置)
为了实现动态的过期时间,在定义队列时,需要我们手动设置一个极大的过期时间
// 创建队列
@Bean
public Queue queueLog() {
Map<String, Object> args = new HashMap<>();
args.put("x-message-ttl", TTL_MAX); // 设置消息最大存活时间为 24h
args.put("x-dead-letter-exchange", EXCHANGE_DLX_LOG); // 设置死信交换机
args.put("x-dead-letter-routing-key", ROUTING_KEY_LOG); // 设置死信路由键
return QueueBuilder.durable(QUEUE_LOG).withArguments(args).build();
}
这里的TTL_MAX 我设置的就是24h(信息时间的单位是毫秒,在设置时间时记得换算一下)
在信息的发送上按以下代码为示例,需要以AmqpTemplate 类型一个实例化的mq工具
计算现在时间到目标时间 的时间差(注意单位换算,毫秒)
@Autowired
private AmqpTemplate rabbitTemplate;
/*
* 发送消息 验证签到
* */
public void sendLogMessage(String message) {
log.info("发送消息:" + message + "到签到队列");
QueryWrapper<ReservationsDTO> qw = new QueryWrapper<>();
qw.eq("reservation_id", message);
ReservationsDTO dto = reservationsMapper.selectOne(qw);
MessageProperties messageProperties = new MessageProperties();
// 获取 startTime
LocalDateTime startTime = dto.getStartTime();
// 计算当前时间到 startTime 的时间差
Duration duration = Duration.between(LocalDateTime.now(), startTime);
//这里可能存在负数情况,虽然正常情况不会有 防范于未然
if(duration.isNegative()) {
log.error(message + "签到时间已过....");
duration = Duration.ZERO;
}
long expirationTimeMinutes = duration.toMillis(); // 转换为毫秒
messageProperties.setExpiration(String.valueOf(expirationTimeMinutes));
// 第一个位置是队列名称,信息,和设置的过期时间
rabbitTemplate.convertAndSend(RabbitMQ.EXCHANGE, message, msg -> {
msg.getMessageProperties().setExpiration(messageProperties.getExpiration());
return msg;
});
// 如果你需要路由键设置 按下面这个来即可
/**
* rabbitTemplate.convertAndSend(RabbitMQ.EXCHANGE,"路由键", message, msg -> {
* msg.getMessageProperties().setExpiration(messageProperties.getExpiration());
* return msg;
* });
*
*/
}
注意 你设置的过期时间不要超过你配置的最大过期时间,所以在设置的时间就考虑好极端情况的最大时间是多少,最后在你的消费者监听对应的死信队列,正常编写业务逻辑即可
标签:JAVA,过期,队列,死信,MQ,设置,msg,时间,message From: https://blog.csdn.net/2301_79425914/article/details/144372955