Rabbitmq插件下载地址:https://www.rabbitmq.com/community-plugins.html
选择rabbitmq_delayed_message_exchange(一个向RabbitMQ添加延迟消息(或计划消息)的插件)进行下载
现在下载的版本是3.7或者3.8,所以rabbitmq需要3.7以上
下面是rabbitmq_delayed_message_exchange的下载地址:
ez版本:https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/download/v3.8.0/rabbitmq_delayed_message_exchange-3.8.0.ez
zip版本:https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/archive/v3.8.0.zip
gz版本:https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/archive/v3.8.0.tar.gz
Rabbitmq安装插件的方法:Rabbitmq服务器不附带的所有插件都需要安装。安装方式为将以.ez存档(带有元数据的zip文件)的插件文件。复制或者放到RABBITMQ_PLUGINS_DIR 文件夹下,RABBITMQ_PLUGINS_DIR即rabbitmq安装目录下的plugins目录。通过rabbitmq-plugins enable命令来启动插件,可以通过rabbitmq-plugins list命令来查看Rabbitmq已经安装的插件。
先移动到rabbitmq的安装目录下的plugins目录,使用上面的下载地址来下载插件。(我直接下载的是ez版本,plugins下的插件需要的就是ez版本,所以不用解压操作什么的)
wget https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/download/v3.8.0/rabbitmq_delayed_message_exchange-3.8.0.ez
下载完成之后,进入sbin目录启用插件:
./rabbitmq-plugins enable rabbitmq_delayed_message_exchange
然后检查安装的插件,看是否安装成功(看是否有rabbitmq_delayed_message相关的插件)
./rabbitmq-plugins list
还可以直接在rabbitmq的管理页面的添加交换机的Type属性上看是否多了个x-delayed-message,如果有,说明安装成功
windows下的安装方法也是一样的,只是以下两条命令有所不同而已
进入sbin目录启用插件:
#windows
./rabbitmq-plugins.bat enable rabbitmq_delayed_message_exchange
查看安装的插件
#windows
./rabbitmq-plugins.bat list
安装完成之后,我们就可以使用延迟队列了
插件方式实现延迟队列的流程如下:
1、生产者将一个设置有延迟时间的消息(msg)和路由键(routekey)发送指定的延时交换机(exchange)上
2、延时交换机(exchange)存储消息等待消息到期根据路由键(routekey)找到绑定自己的队列(queue)并把消息给它
3、队列(queue)再把消息发送给监听它的消费者(customer)
相对于TTL实现延迟队列,插件方式实现较简单,也无需定义那么多的rabbitmq组件。
实例
1、进行延时交换机和延迟队列的注册
//下面是一个延迟队列的注册类
@Configuration
public class RabbitmaqConfig {
/**
* 延时交换机,交换机类型为CustomExchange
*/
@Bean
public CustomExchange customExchange(){
Map<String,Object>args=new HashMap<>();
//延时交换机一定要设置x-delayed-type属性
args.put("x-delayed-type", "direct");
//第二个参数type需要设置成x-delayed-message
return new CustomExchange("delay_exchange","x-delayed-message",true,false,args);
}
/**
* 延时队列
* @return
*/
@Bean
public Queue delayQueue(){
return new Queue("delay_queue",true);
}
/**
* 延时队列绑定交换机
* @return
*/
@Bean
public Binding delayBinding(){
return BindingBuilder.bind(delayQueue()).to(customExchange()).with("delay_key").noargs();
}
}
说明:插件的延迟消息主要是通过延迟交换机来实现的,所以我们在注册延迟交换机时必须添加上x-delayed-type属性,并且声明消息类型为x-delayed-message,而不是普通的交换机。
2、延时消息发送类
@Component
@Slf4j
public class RabbitmqSend {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送延时消息
* @param msg
*/
public void sendDelayMessage(Object msg,Long delayTime){
rabbitTemplate.convertAndSend( "delay_exchange", "delay_key",msg,
message -> {
//设置延迟时间
message.getMessageProperties().setHeader("x-delay",delayTime);
return message;
});
log.info("发送延迟消息:{},延时:{}毫秒",msg,delayTime);
}
}
说明:插件类的延时消息,只需要在header上设置x-delay值即可,单位为毫秒
消费类跟普通的消息消费类一样
简单写一个消费类
@Component
@Slf4j
public class RabbitmqRecover {
@RabbitListener(queues = "delay_queue")
public void recover(String msg,Message message, Channel channel){
log.info("接收时间:{},接受内容:{}", LocalDateTime.now(), msg);
//通知 MQ 消息已被接收,可以ACK(从队列中删除)了
try {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}catch (Exception e){
log.error("消息消费失败!错误信息:{}",e.getMessage());
}
}
}
测试一下
@RestController
public class RabbitmqController {
@Autowired
private RabbitmqProduce produce;
@Autowired
private RabbitmqSend sender;
@GetMapping("/rabbitmq")
public void send() throws Exception {
sender.sendDelayMessage("这是一个延迟消息",6000L);
}
}
调用接口,输出以下结果,可以看到,发送和消费刚好相差6秒,实现延迟队列成功!
2020-07-06 15:58:08.431 INFO 40620 --- [nio-8080-exec-1] com.example.demo.rabbitmq.RabbitmqSend : 发送延迟消息:这是一个延迟消息,延时:6000毫秒
2020-07-06 15:58:14.477 INFO 40620 --- [ntContainer#1-2] c.example.demo.rabbitmq.RabbitmqRecover : 接收时间:2020-07-06T15:58:14.477868600,接受内容:这是一个延迟消息,headers:{__TypeId__=java.lang.String}