Spring Boot(十四)RabbitMQ延迟队列

一、前言

延迟队列的使用场景:1.未按时支付的订单,30分钟过期之后取消订单;2.给活跃度比较低的用户间隔N天之后推送消息,提高活跃度;3.过1分钟给新注册会员的用户,发送注册邮件等。

实现延迟队列的方式有两种:

  1. 通过消息过期后进入死信交换器,再由交换器转发到延迟消费队列,实现延迟功能;
  2. 使用rabbitmq-delayed-message-exchange插件实现延迟功能;

注意: 延迟插件rabbitmq-delayed-message-exchange是在RabbitMQ 3.5.7及以上的版本才支持的,依赖Erlang/OPT 18.0及以上运行环境。

由于使用死信交换器相对曲折,本文重点介绍第二种方式,使用rabbitmq-delayed-message-exchange插件完成延迟队列的功能。

二、安装延迟插件

1.1 下载插件

打开官网下载:http://www.rabbitmq.com/community-plugins.html

选择相应的对应的版本“3.7.x”点击下载。

注意: 下载的是.zip的安装包,下载完之后需要手动解压。

1.2 安装插件

拷贝插件到Docker:

docker cp D:\rabbitmq_delayed_message_exchange-20171201-3.7.x.ez rabbit:/plugins

RabbitMQ在Docker的安装,请参照本系列的上一篇文章:http://www.apigo.cn/2018/09/11/springboot13/

1.3 启动插件

进入docker内部:

docker exec -it rabbit /bin/bash

开启插件:

rabbitmq-plugins enable rabbitmq_delayed_message_exchange

查询安装的所有插件:

rabbitmq-plugins list

安装正常,效果如下图:

重启RabbitMQ,使插件生效

docker restart rabbit

三、代码实现

3.1 配置队列

1import com.example.rabbitmq.mq.DirectConfig; 2import org.springframework.amqp.core.*; 3import org.springframework.context.annotation.Bean; 4import org.springframework.context.annotation.Configuration; 5import java.util.HashMap; 6import java.util.Map; 7 8@Configuration 9public class DelayedConfig { 10 final static String QUEUE_NAME = "delayed.goods.order"; 11 final static String EXCHANGE_NAME = "delayedec"; 12 @Bean 13 public Queue queue() { 14 return new Queue(DelayedConfig.QUEUE_NAME); 15 } 16 17 // 配置默认的交换机 18 @Bean 19 CustomExchange customExchange() { 20 Map<String, Object> args = new HashMap<>(); 21 args.put("x-delayed-type", "direct"); 22 //参数二为类型:必须是x-delayed-message 23 return new CustomExchange(DelayedConfig.EXCHANGE_NAME, "x-delayed-message", true, false, args); 24 } 25 // 绑定队列到交换器 26 @Bean 27 Binding binding(Queue queue, CustomExchange exchange) { 28 return BindingBuilder.bind(queue).to(exchange).with(DelayedConfig.QUEUE_NAME).noargs(); 29 } 30}

3.2 发送消息

1import org.springframework.amqp.AmqpException; 2import org.springframework.amqp.core.AmqpTemplate; 3import org.springframework.amqp.core.Message; 4import org.springframework.amqp.core.MessagePostProcessor; 5import org.springframework.beans.factory.annotation.Autowired; 6import org.springframework.stereotype.Component; 7import java.text.SimpleDateFormat; 8import java.util.Date; 9 10@Component 11public class DelayedSender { 12 @Autowired 13 private AmqpTemplate rabbitTemplate; 14 15 public void send(String msg) { 16 SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 17 System.out.println("发送时间:" + sf.format(new Date())); 18 19 rabbitTemplate.convertAndSend(DelayedConfig.EXCHANGE_NAME, DelayedConfig.QUEUE_NAME, msg, new MessagePostProcessor() { 20 @Override 21 public Message postProcessMessage(Message message) throws AmqpException { 22 message.getMessageProperties().setHeader("x-delay", 3000); 23 return message; 24 } 25 }); 26 } 27}

3.3 消费消息

1import org.springframework.amqp.rabbit.annotation.RabbitHandler; 2import org.springframework.amqp.rabbit.annotation.RabbitListener; 3import org.springframework.stereotype.Component; 4import java.text.SimpleDateFormat; 5import java.util.Date; 6 7@Component 8@RabbitListener(queues = "delayed.goods.order") 9public class DelayedReceiver { 10 @RabbitHandler 11 public void process(String msg) { 12 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 13 System.out.println("接收时间:" + sdf.format(new Date())); 14 System.out.println("消息内容:" + msg); 15 } 16}

3.4 测试队列

1import com.example.rabbitmq.RabbitmqApplication; 2import com.example.rabbitmq.mq.delayed.DelayedSender; 3import org.junit.Test; 4import org.junit.runner.RunWith; 5import org.springframework.beans.factory.annotation.Autowired; 6import org.springframework.boot.test.context.SpringBootTest; 7import org.springframework.test.context.junit4.SpringRunner; 8 9import java.text.SimpleDateFormat; 10import java.util.Date; 11 12@RunWith(SpringRunner.class) 13@SpringBootTest 14public class DelayedTest { 15 16 @Autowired 17 private DelayedSender sender; 18 19 @Test 20 public void Test() throws InterruptedException { 21 SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd"); 22 sender.send("Hi Admin."); 23 Thread.sleep(5 * 1000); //等待接收程序执行之后,再退出测试 24 } 25}

执行结果如下:

1发送时间:2018-09-11 20:47:51 2接收时间:2018-09-11 20:47:54 3消息内容:Hi Admin.

完整代码访问我的GitHub:https://github.com/vipstone/springboot-example/tree/master/springboot-rabbitmq

四、总结

到此为止我们已经使用“rabbitmq-delayed-message-exchange”插件实现了延迟功能,但是需要注意的一点是,如果使用命令“rabbitmq-plugins disable rabbitmq_delayed_message_exchange”禁用了延迟插件,那么所有未发送的延迟消息都将丢失。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

Spring Boot(十四)RabbitMQ延迟队列 - HelloWorld