Spring Boot(十四)RabbitMQ延迟队列
一、前言
延迟队列的使用场景:1.未按时支付的订单,30分钟过期之后取消订单;2.给活跃度比较低的用户间隔N天之后推送消息,提高活跃度;3.过1分钟给新注册会员的用户,发送注册邮件等。
实现延迟队列的方式有两种:
- 通过消息过期后进入死信交换器,再由交换器转发到延迟消费队列,实现延迟功能;
- 使用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 配置队列
import com.example.rabbitmq.mq.DirectConfig;
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;
@Configuration
public class DelayedConfig {
final static String QUEUE_NAME = "delayed.goods.order";
final static String EXCHANGE_NAME = "delayedec";
@Bean
public Queue queue() {
return new Queue(DelayedConfig.QUEUE_NAME);
}
// 配置默认的交换机
@Bean
CustomExchange customExchange() {
Map<String, Object> args = new HashMap<>();
args.put("x-delayed-type", "direct");
//参数二为类型:必须是x-delayed-message
return new CustomExchange(DelayedConfig.EXCHANGE_NAME, "x-delayed-message", true, false, args);
}
// 绑定队列到交换器
@Bean
Binding binding(Queue queue, CustomExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(DelayedConfig.QUEUE_NAME).noargs();
}
}
3.2 发送消息
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
public class DelayedSender {
@Autowired
private AmqpTemplate rabbitTemplate;
public void send(String msg) {
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("发送时间:" + sf.format(new Date()));
rabbitTemplate.convertAndSend(DelayedConfig.EXCHANGE_NAME, DelayedConfig.QUEUE_NAME, msg, new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setHeader("x-delay", 3000);
return message;
}
});
}
}
3.3 消费消息
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
@RabbitListener(queues = "delayed.goods.order")
public class DelayedReceiver {
@RabbitHandler
public void process(String msg) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("接收时间:" + sdf.format(new Date()));
System.out.println("消息内容:" + msg);
}
}
3.4 测试队列
import com.example.rabbitmq.RabbitmqApplication;
import com.example.rabbitmq.mq.delayed.DelayedSender;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.text.SimpleDateFormat;
import java.util.Date;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DelayedTest {
@Autowired
private DelayedSender sender;
@Test
public void Test() throws InterruptedException {
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
sender.send("Hi Admin.");
Thread.sleep(5 * 1000); //等待接收程序执行之后,再退出测试
}
}
执行结果如下:
发送时间:2018-09-11 20:47:51
接收时间:2018-09-11 20:47:54
消息内容:Hi Admin.
完整代码访问我的GitHub:https://github.com/vipstone/springboot-example/tree/master/springboot-rabbitmq
四、总结
到此为止我们已经使用“rabbitmq-delayed-message-exchange”插件实现了延迟功能,但是需要注意的一点是,如果使用命令“rabbitmq-plugins disable rabbitmq_delayed_message_exchange”禁用了延迟插件,那么所有未发送的延迟消息都将丢失。
Spring Boot(十四)RabbitMQ延迟队列的更多相关文章
- Spring Boot(十四):spring boot整合shiro-登录认证和权限管理
Spring Boot(十四):spring boot整合shiro-登录认证和权限管理 使用Spring Boot集成Apache Shiro.安全应该是互联网公司的一道生命线,几乎任何的公司都会涉 ...
- (转)Spring Boot (十四): Spring Boot 整合 Shiro-登录认证和权限管理
http://www.ityouknow.com/springboot/2017/06/26/spring-boot-shiro.html 这篇文章我们来学习如何使用 Spring Boot 集成 A ...
- spring boot(十四)shiro登录认证与权限管理
这篇文章我们来学习如何使用Spring Boot集成Apache Shiro.安全应该是互联网公司的一道生命线,几乎任何的公司都会涉及到这方面的需求.在Java领域一般有Spring Security ...
- Spring Boot (十四): Spring Boot 整合 Shiro-登录认证和权限管理
这篇文章我们来学习如何使用 Spring Boot 集成 Apache Shiro .安全应该是互联网公司的一道生命线,几乎任何的公司都会涉及到这方面的需求.在 Java 领域一般有 Spring S ...
- Spring RabbitMQ 延迟队列
一.说明 在实际业务场景中可能会用到延时消息发送,例如异步回调失败时的重发机制. RabbitMQ本身不具有延时消息队列的功能,但是可以通过rabbitmq-delayed-message-excha ...
- Spring Boot(八):RabbitMQ详解
Spring Boot(八):RabbitMQ详解 RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用. 消息中间件在互联网公司的使用中越来越多 ...
- spring boot / cloud (四) 自定义线程池以及异步处理@Async
spring boot / cloud (四) 自定义线程池以及异步处理@Async 前言 什么是线程池? 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线 ...
- Spring Boot (十):邮件服务
Spring Boot 仍然在狂速发展,才几个多月没有关注,现在看官网已经到 2.1.0.RELEASE 版本了.准备慢慢在写写 Spring Boot 相关的文章,本篇文章使用 Spring Boo ...
- (转)Spring Boot (十):邮件服务
http://www.ityouknow.com/springboot/2017/05/06/spring-boot-mail.html Spring Boot 仍然在狂速发展,才几个多月没有关注,现 ...
- C# RabbitMQ延迟队列功能实战项目演练
一.需求背景 当用户在商城上进行下单支付,我们假设如果8小时没有进行支付,那么就后台自动对该笔交易的状态修改为订单关闭取消,同时给用户发送一份邮件提醒.那么我们应用程序如何实现这样的需求场景呢?在之前 ...
随机推荐
- [转]C# 使用Conditional特性而不是#if条件编译
转自: http://www.cnblogs.com/xibei666/p/5495561.html 概述 #if/#endif 语句常用来基于同一份源码生成不同的编译结果,其中最常见的就是debug ...
- css实现中文换行,英文换行,超出省略
英文换行时,是以单词换行,在对应的标签添加对应的属性即可 1 word-break:break-all;只对英文起作用,以字母作为换行依据 2 word-wrap:break-word; 只对英文起作 ...
- linux系统资源监控
top命令 1.平均负载(load average): 正在耗费CPU进程与正在等待io的进程之和,三个值分别是一分钟,五分钟,十五分钟的平均负载,负载值只要小于CPU颗粒数属于正常情况 任务进程(T ...
- 创建一个git仓库
1.git init 使用git init命令初始化一个git仓库,git仓库会生成一个.git目录 git init 1.使用指定的目录作为我们的git仓库 git init newrepo 2.初 ...
- 让数字变化炫酷起来,数字滚动Text组件[Unity]
让数字滚动起来 上周我的策划又提了样需求,当玩家评分发生变动时,屏幕出现人物评分浮层UI,播放评分数字滚动动画.这类数字滚动需求非常常见,我就按一般思路,将startvalue与endvalue每隔一 ...
- 怎么用JQUERY设置div背景图片?
平常,在css里,我们写成 { background:url(....) ; } 如果需要写脚本, 则 function(){ .....; $(....).css("background- ...
- ubuntu系统界面改变
主题:https://gitzab.com/Anduin/GNOME-OSX-II-Theme.git图标:https://github.com/keeferrourke/la-capitaine-i ...
- LeetCode724. 寻找数组的中心索引
1.题目描述 给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法. 我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和. 如果数组不存在中 ...
- 【从零开始搭建自己的.NET Core Api框架】(二)搭建项目的整体架构
系列目录 一. 创建项目并集成swagger 1.1 创建 1.2 完善 二. 搭建项目整体架构 三. 集成轻量级ORM框架——SqlSugar 3.1 搭建环境 3.2 实战篇:利用SqlSuga ...
- [Swift]LeetCode652. 寻找重复的子树 | Find Duplicate Subtrees
Given a binary tree, return all duplicate subtrees. For each kind of duplicate subtrees, you only ne ...