一、前言

延迟队列的使用场景: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 配置队列

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延迟队列的更多相关文章

  1. Spring Boot(十四):spring boot整合shiro-登录认证和权限管理

    Spring Boot(十四):spring boot整合shiro-登录认证和权限管理 使用Spring Boot集成Apache Shiro.安全应该是互联网公司的一道生命线,几乎任何的公司都会涉 ...

  2. (转)Spring Boot (十四): Spring Boot 整合 Shiro-登录认证和权限管理

    http://www.ityouknow.com/springboot/2017/06/26/spring-boot-shiro.html 这篇文章我们来学习如何使用 Spring Boot 集成 A ...

  3. spring boot(十四)shiro登录认证与权限管理

    这篇文章我们来学习如何使用Spring Boot集成Apache Shiro.安全应该是互联网公司的一道生命线,几乎任何的公司都会涉及到这方面的需求.在Java领域一般有Spring Security ...

  4. Spring Boot (十四): Spring Boot 整合 Shiro-登录认证和权限管理

    这篇文章我们来学习如何使用 Spring Boot 集成 Apache Shiro .安全应该是互联网公司的一道生命线,几乎任何的公司都会涉及到这方面的需求.在 Java 领域一般有 Spring S ...

  5. Spring RabbitMQ 延迟队列

    一.说明 在实际业务场景中可能会用到延时消息发送,例如异步回调失败时的重发机制. RabbitMQ本身不具有延时消息队列的功能,但是可以通过rabbitmq-delayed-message-excha ...

  6. Spring Boot(八):RabbitMQ详解

    Spring Boot(八):RabbitMQ详解 RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用. 消息中间件在互联网公司的使用中越来越多 ...

  7. spring boot / cloud (四) 自定义线程池以及异步处理@Async

    spring boot / cloud (四) 自定义线程池以及异步处理@Async 前言 什么是线程池? 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线 ...

  8. Spring Boot (十):邮件服务

    Spring Boot 仍然在狂速发展,才几个多月没有关注,现在看官网已经到 2.1.0.RELEASE 版本了.准备慢慢在写写 Spring Boot 相关的文章,本篇文章使用 Spring Boo ...

  9. (转)Spring Boot (十):邮件服务

    http://www.ityouknow.com/springboot/2017/05/06/spring-boot-mail.html Spring Boot 仍然在狂速发展,才几个多月没有关注,现 ...

  10. C# RabbitMQ延迟队列功能实战项目演练

    一.需求背景 当用户在商城上进行下单支付,我们假设如果8小时没有进行支付,那么就后台自动对该笔交易的状态修改为订单关闭取消,同时给用户发送一份邮件提醒.那么我们应用程序如何实现这样的需求场景呢?在之前 ...

随机推荐

  1. Idea下的springboot mysql8.0等报错解决随笔

    cannot load jdbc class path:mysql8.0装载失败,可能原因,驱动名称错误,连接字符串中需要加入时区UTC,否则8.0一定会报错无法连接,关闭SSL 在applicati ...

  2. Docker-Compose入门

    转:https://blog.csdn.net/chinrui/article/details/79155688

  3. 串口RS232和485通信的波形分析

    一.串行数据的格式 异步串行数据的一般格式是:起始位+数据位+停止位,其中起始位1 位,数据位可以是5.6.7.8位,停止位可以是1.1.5.2位. 起始位是一个值为0的位,所以对于正逻辑的TTL电平 ...

  4. leetcode-比特位计数

    一.题目描述 给定一个非负整数 num.对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回. 示例 1: 输入: 2 输出: [0,1,1] 示例 ...

  5. Web安全之XSS Platform搭建及使用实践

    Web安全之XSS Platform搭建及使用实践 一.背景 XSS Platform 是一个非常经典的XSS渗透测试管理系统,原作者在2011年所开发,由于后来长时间没有人维护,导致目前在PHP7环 ...

  6. 开源播放器 ijkplayer (六) :Android 下使用 ijkplayer 异常处理思路

    一. java.lang.IllegalStateException: mpjni: setOptionLong: null mp 根据已查到的资料看,目前是ijk内部的问题,只能通过try& ...

  7. [Swift]LeetCode409. 最长回文串 | Longest Palindrome

    Given a string which consists of lowercase or uppercase letters, find the length of the longest pali ...

  8. [Swift]LeetCode581. 最短无序连续子数组 | Shortest Unsorted Continuous Subarray

    Given an integer array, you need to find one continuous subarray that if you only sort this subarray ...

  9. [Swift]LeetCode592. 分数加减运算 | Fraction Addition and Subtraction

    Given a string representing an expression of fraction addition and subtraction, you need to return t ...

  10. [Swift]LeetCode809. 情感丰富的文字 | Expressive Words

    Sometimes people repeat letters to represent extra feeling, such as "hello" -> "he ...