实现延时队列逻辑
RabbitMQ是没有直接实现延时队列的,可以使用死信队列或者是插件的形式实现延时队列。
本次质演示使用死信队列实现延时队列。
思想:生产者正常往RabbitMQ的正常队列中发送消息。不过这里给队列设置了TTL(消息在此队列的存活时间)。超过TTL后,消息则会进入死信队列。然后由监听死信队列的消费者消费此条消息。以此实现消息的延时。
RabbitMQConfig
队列以及交换机的配置文件
java
//正常队列,消息只存在10秒,如果没有人消费,则进入死信队列,做延时消费
@Bean("normalQueue")
public Queue normalQueue() {
return QueueBuilder.durable(Constants.NORMAL_QUEUE).ttl(10000).deadLetterExchange(Constants.DL_EXCHANGE).deadLetterRoutingKey("dl").build();
}
//正常消息的交换机
@Bean("normalExchange")
public DirectExchange normalExchange() {
return ExchangeBuilder.directExchange(Constants.NORMAL_EXCHANGE).build();
}
//绑定关系
@Bean("normalBinding")
public Binding normalBinding(@Qualifier("normalQueue") Queue queue, @Qualifier("normalExchange") DirectExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with("normal");
}
//死信队列
@Bean("dlQueue")
public Queue dlQueue() {
return QueueBuilder.durable(Constants.DL_QUEUE).build();
}
//死信交换机
@Bean("dlExchange")
public DirectExchange dlExchange() {
return ExchangeBuilder.directExchange(Constants.DL_EXCHANGE).build();
}
//死信绑定关系
@Bean("dlBinding")
public Binding dlBinding(@Qualifier("dlQueue") Queue queue, @Qualifier("dlExchange") DirectExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with("dl");
}
生产者
java
public String sendMessage() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
rabbitTemplate.convertAndSend(Constants.NORMAL_EXCHANGE,"normal","hello direct " + i);
System.out.printf("%tc 消息发送成功 \n",new Date());
}
return "test fanout success...";
}
消费者消费消息
这里只消费死信队列即可,正常的队列不消费,直接等待消息过期,进入死信队列
java
@RabbitListener(queues = "dl")
public void messageHandler(Message message) throws UnsupportedEncodingException {
long deliveryTag = message.getMessageProperties().getDeliveryTag();
System.out.printf("[delay.queue] %tc 接收到消息: %s, deliveryTag: %d \n",new Date(),new String(message.getBody(),"UTF-8"),deliveryTag);
//业务处理
}