(一)RabbitMq开启延迟队列
rabbitmq 延迟队列的实现,需要插件的支持
参考 :docker 安装 rabbitmq并添加延迟队列插件
(二)项目设置
(1)依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
(2)yml配置
spring:
rabbitmq:
host: xxx
port: xxx
username: xxx
password: xxx
(三)延迟消息实现核心配置
延迟对列的实现,实质主要是要定义且配置一个延迟交换机
@Bean
public Exchange delayExchange() {
Map<String, Object> args = new HashMap<>(2);
// x-delayed-type 声明 延迟交换机的类型为路由直连
args.put("x-delayed-type", "direct");
// 设置名字 交换机类型(延迟消息) 持久化 不自动删除
return new CustomExchange("test-delayed-exchange", "x-delayed-message", true, false, args);
}
核心:
自定义参数定义交换机类型:
Map<String, Object> args = new HashMap<>(2);
args.put("x-delayed-type", "direct");
申明交换机中的消息为延迟消息:
上边CustomExchange
构造器中的第二个参数x-delayed-message
我们接下来进行一个完整的配置定义,我们定义交换机,定义队列,队列交换机路由件绑定
package com.leilei.delayed;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* @author lei
* @version 1.0
* @date 2021/9/19 18:25
* @desc rabbitMq延迟消息配置示例 (rabbitmq需安装 延迟消息插件 http://www.rabbitmq.com/community-plugins.html)
*/
@Configuration
public class RabbitMqDelayedConfig {
@Bean
public Exchange delayExchange() {
Map<String, Object> args = new HashMap<>(2);
// x-delayed-type 声明 延迟队列Exchange的类型
args.put("x-delayed-type", "direct");
// 设置名字 交换机类型 持久化 不自动删除
return new CustomExchange("test-delayed-exchange", "x-delayed-message", true, false, args);
}
@Bean
public Queue delayQueue() {
return QueueBuilder.durable("test-delayed-queue").build();
}
/**
* 将延迟队列通过routingKey绑定到延迟交换器
*
* @return
*/
@Bean
public Binding delayQueueBindExchange(Exchange delayExchange, Queue delayQueue) {
return BindingBuilder.bind(delayQueue).to(delayExchange).with("leilei").noargs();
}
}
(四)发送延迟消息
(1)延迟消息生产者
延迟消息的发送,与普通队列发送消息大部分一致,但我们需要对message做额外的延时配置
EX:
@Service
public class DelayedProvider {
private final AmqpTemplate rabbitTemplate;
@Autowired
public DelayedProvider(AmqpTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}
public void send(int delayedTime, String messageBody) {
// 指定之前定义的延迟交换机名 与路由键名
rabbitTemplate.convertAndSend("test-delayed-exchange", "leilei", messageBody, message -> {
// 延迟时间单位是毫秒
message.getMessageProperties().setDelay(delayedTime);
System.out.println("消息发送时间:" + LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm:ss")) +
"消息内容:" + messageBody);
return message;
});
}
}
(2)延迟消息消费者
消费者端与普通的MQ消费者,一致,只需要监听对应的队列即可
@Service
public class DelayedConsumer {
@RabbitListener(queues = "test-delayed-queue")
public void testListenerDelayedMessage(Message message) {
byte[] body = message.getBody();
System.out.println(LocalDateTime.now() + new String(body));
}
}
(五)测试
延迟15S
延迟5s
![image-20210921205921335](https://leileidev.oss-cn-chengdu.aliyuncs.com/img/image-20210921205921335.png)