Rabbitmq实时队列很多人都用过,本文就讲解下延时队列。延时队列的使用场景有很多,一般用来做延时的消息推送,比如订单取消前的通知,还有消息通知。
首先定义消息通知队列枚举类型
@Getter
public enum QueueEnum {
/**
* 消息推送队列
*/
QUEUE_PUSH_MESSGAE("mall.pushMessgae.direct", "mall.pushMessgae", "mall.pushMessgae"),
/**
* 消息推送 TTL 队列
*/
QUEUE_TTL_PUSH_MESSGAE("mall.pushMessgae.direct.ttl", "mall.pushMessgae.ttl", "mall.pushMessgae.ttl");
/**
* 交换名称
*/
private String exchange;
/**
* 队列名称
*/
private String name;
/**
* 路由键
*/
private String routeKey;
QueueEnum(String exchange, String name, String routeKey) {
this.exchange = exchange;
this.name = name;
this.routeKey = routeKey;
}
}
配置RabbitConfig,绑定队列和Exchange
@Configuration
public class RabbitMqConfig {
/**
* 消息推送队列所绑定的交换机
*/
@Bean
DirectExchange pushMessage() {
return (DirectExchange) ExchangeBuilder
.directExchange(QueueEnum.QUEUE_PUSH_MESSGAE.getExchange())
.durable(true)
.build();
}
/**
* 消息推送 TTL 队列列所绑定的交换机
*/
@Bean
DirectExchange pushTtlMessage() {
return (DirectExchange) ExchangeBuilder
.directExchange(QueueEnum.QUEUE_TTL_PUSH_MESSGAE.getExchange())
.durable(true)
.build();
}
/**
* 消息推送队列
*/
@Bean
public Queue pushMessageQueue() {
return new Queue(QueueEnum.QUEUE_PUSH_MESSGAE.getName());
}
/**
* 消息推送延迟队列(死信队列)
*/
@Bean
public Queue pushMessageTtlQueue() {
return QueueBuilder
.durable(QueueEnum.QUEUE_TTL_PUSH_MESSGAE.getName())
// 到期后转发的交换机
.withArgument("x-dead-letter-exchange", QueueEnum.QUEUE_PUSH_MESSGAE.getExchange())
// 到期后转发的路由键
.withArgument("x-dead-letter-routing-key", QueueEnum.QUEUE_PUSH_MESSGAE.getRouteKey())
.build();
}
/**
* 将消息推送队列绑定到交换机
*/
@Bean
Binding pushMessageBinding(DirectExchange pushMessage, Queue pushMessageQueue) {
return BindingBuilder
.bind(pushMessageQueue)
.to(pushMessage)
.with(QueueEnum.QUEUE_PUSH_MESSGAE.getRouteKey());
}
/**
* 将消息推送延迟队列绑定到交换机
*/
@Bean
Binding pushMessageTtlBinding(DirectExchange pushTtlMessage, Queue pushMessageTtlQueue) {
return BindingBuilder
.bind(pushMessageTtlQueue)
.to(pushTtlMessage)
.with(QueueEnum.QUEUE_TTL_PUSH_MESSGAE.getRouteKey());
}
}
生产者
@Slf4j
@Component
public class PushMessageSender {
@Autowired
private AmqpTemplate amqpTemplate;
/**
* 发送延迟队列消息
*
* @param pushMessageDto 订单ID
* @param delayTimes 延迟时间(毫秒)
*/
public void sendMessage(PushMessageDto pushMessageDto, final long delayTimes) {
// 给延迟队列发送消息
amqpTemplate.convertAndSend(QueueEnum.QUEUE_TTL_PUSH_MESSGAE.getExchange(),
QueueEnum.QUEUE_TTL_PUSH_MESSGAE.getRouteKey(), pushMessageDto ,
message -> {
// 给消息设置延迟毫秒值
message.getMessageProperties().setExpiration(String.valueOf(delayTimes));
return message;
});
}
/**
* 发送实时队列消息
*
* @param pushMessageDto
*
*/
public void sendMessage(PushMessageDto pushMessageDto) {
// 发送实时队列消息
amqpTemplate.convertAndSend(QueueEnum.QUEUE_PUSH_MESSGAE.getExchange(),
QueueEnum.QUEUE_PUSH_MESSGAE.getRouteKey(), pushMessageDto);
}
}
消费者
@Slf4j
@Component
@RabbitListener(queues = "mall.pushMessgae")
public class PushMessageReceiver {
@Autowired
private IMessagesendService messagesendService;
/**
* 处理消息推送
*
* @param pushMessageDto 订单ID userid
*/
@RabbitHandler
public void handle(PushMessageDto pushMessageDto){
log.info("[订单延迟队列] 接收延迟队列消息:订单编号={},用户ID={}", pushMessageDto.getOrderNo(), pushMessageDto.getUserId());
messagesendService.MessagePush(pushMessageDto.getUserId(),pushMessageDto.getOrderNo(),pushMessageDto.getType());
}
}