一、说明

在实际业务场景中可能会用到延时消息发送,例如异步回调失败时的重发机制。 RabbitMQ本身不具有延时消息队列的功能,但是可以通过rabbitmq-delayed-message-exchange来实现(也可以通过TTL(Time To Live)、DLX(Dead Letter Exchanges)特性实现,我们主要讲解通过延迟插件来实现的方法)。利用RabbitMQ的这种特性,应该可以实现很多现实中的业务,我们可以发挥想象。

二、安装插件

RabbitMQ的安装请参考我的文章“RabbitMQ安装与使用”,这里我们重点讲插件的安装。

首先到http://www.rabbitmq.com/community-plugins.html网页下载适合的“rabbitmq_delayed_message_exchange插件”。下载完成后将它放到RabbitMQ插件安装目录({rabbitmq-server}/plugins/),然后执行命令rabbitmq-plugins enable rabbitmq_delayed_message_exchange启用插件,执行命令rabbitmq-plugins disable rabbitmq_delayed_message_exchange也可以关闭插件。具体过程可以查看参考文档2。

三、spring集成RabbitMQ

1、maven配置

  1. <dependency>
  2. <groupId>org.springframework.amqp</groupId>
  3. <artifactId>spring-amqp</artifactId>
  4. <version>1.6.6.RELEASE</version>
  5. <exclusions>
  6. <exclusion>
  7. <groupId>org.springframework</groupId>
  8. <artifactId>spring-core</artifactId>
  9. <version>4.1.6.RELEASE</version>
  10. </exclusion>
  11. </exclusions>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.springframework.amqp</groupId>
  15. <artifactId>spring-rabbit</artifactId>
  16. <version>1.6.6.RELEASE</version>
  17. <exclusions>
  18. <exclusion>
  19. <groupId>org.springframework</groupId>
  20. <artifactId>spring-core</artifactId>
  21. <version>4.1.6.RELEASE</version>
  22. </exclusion>
  23. <exclusion>
  24. <groupId>org.springframework</groupId>
  25. <artifactId>spring-messaging</artifactId>
  26. <version>4.1.6.RELEASE</version>
  27. </exclusion>
  28. <exclusion>
  29. <groupId>org.springframework</groupId>
  30. <artifactId>spring-tx</artifactId>
  31. <version>4.1.6.RELEASE</version>
  32. </exclusion>
  33. <exclusion>
  34. <groupId>org.springframework</groupId>
  35. <artifactId>spring-context</artifactId>
  36. <version>4.1.6.RELEASE</version>
  37. </exclusion>
  38. </exclusions>
  39. </dependency>

说明:实现延迟队列需要Spring在4.1以上,spring-amqp在1.6以上。

2、xml配置

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
  4. xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:rabbit="http://www.springframework.org/schema/rabbit"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
  7. http://www.springframework.org/schema/context
  8. http://www.springframework.org/schema/context/spring-context-3.1.xsd
  9. http://www.springframework.org/schema/tx
  10. http://www.springframework.org/schema/tx/spring-tx.xsd
  11. http://www.springframework.org/schema/aop
  12. http://www.springframework.org/schema/aop/spring-aop.xsd
  13. http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
  14. http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.6.xsd">
  15. <context:property-placeholder location="classpath:rmq-config.properties" ignore-unresolvable="true"/>
  16. <bean id="connectionFactory" class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
  17. <property name="host" value="${rabbitmq.host}" />
  18. <property name="port" value="${rabbitmq.port}" />
  19. <property name="username" value="${rabbitmq.username}" />
  20. <property name="password" value="${rabbitmq.password}" />
  21. <property name="channelCacheSize" value="${rabbitmq.channel.cacheSize}" />
  22. </bean>
  23. <bean id="orderConsumer" class="com.xxx.rmq.OrderConsumer"></bean>
  24. <bean id="messageConverter" class="org.springframework.amqp.support.converter.SimpleMessageConverter" />
  25. <bean id="jsonMessageConverter" class="org.springframework.amqp.support.converter.Jackson2JsonMessageConverter" />
  26. <rabbit:admin connection-factory="connectionFactory" />
  27. <!-- 延迟消息start -->
  28. <rabbit:topic-exchange name="delay_exchange" delayed="true">
  29. <rabbit:bindings>
  30. <rabbit:binding queue="delay_queue" pattern="order.delay.notify" />
  31. </rabbit:bindings>
  32. </rabbit:topic-exchange>
  33. <rabbit:queue name="delay_queue" durable="true" auto-declare="true" auto-delete="false" />
  34. <rabbit:template id="delayMsgTemplate" connection-factory="connectionFactory" message-converter="jsonMessageConverter" exchange="delay_exchange" />
  35. <rabbit:listener-container connection-factory="connectionFactory" channel-transacted="false" acknowledge="auto" message-converter="jsonMessageConverter">
  36. <rabbit:listener queues="delay_queue" ref="orderConsumer" method="delayMsg" />
  37. </rabbit:listener-container>
  38. <!-- 延迟消息end -->
  39. </beans>

说明:spring-rabbit-1.6.xsd必须是1.6及以上版本,否则会报“元素 'rabbit:topic-exchange' 中不允许出现属性 'delayed'”错误。具体请查看参考文档3。

四、延迟队列的使用

1、发送消息Producer

  1. import net.sf.json.JSONObject;
  2. import org.apache.commons.lang.StringUtils;
  3. import org.springframework.amqp.AmqpException;
  4. import org.springframework.amqp.core.AmqpTemplate;
  5. import org.springframework.amqp.core.Message;
  6. import org.springframework.amqp.core.MessagePostProcessor;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.stereotype.Service;
  9. /**
  10. *
  11. * @author Horace
  12. * @version 创建时间:2016年10月26日 下午6:34:31
  13. */
  14. @Service
  15. public class MessageProducerServiceImpl implements MessageProducerService{
  16. @Autowired
  17. private AmqpTemplate delayMsgTemplate;
  18. @Override
  19. public void delayMsg(JSONObject msg,int delay) {
  20. // TODO Auto-generated method stub
  21. final int xdelay= delay*1000;
  22. delayMsgTemplate.convertAndSend("order.delay.notify", (Object) msg,
  23. new MessagePostProcessor() {
  24. @Override
  25. public Message postProcessMessage(Message message)
  26. throws AmqpException {
  27. // TODO Auto-generated method stub
  28. message.getMessageProperties().setDelay(xdelay);
  29. return message;
  30. }
  31. });
  32. }
  33. }

2、异步接收消息Consumer

  1. import net.sf.json.JSONObject;
  2. import org.apache.commons.lang.StringUtils;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. /**
  7. *
  8. * @author Horace
  9. * @version 创建时间:2016年10月26日 下午2:48:14
  10. */
  11. public class OrderConsumer {
  12. private static Logger logger = LoggerFactory.getLogger(OrderConsumer.class);
  13. @Autowired
  14. private MessageProducerService messageProducerService;
  15. public void delayMsg(Object obj) {
  16. logger.info("[延时消息]" + obj);
  17. if (obj != null) {
  18. JSONObject notifyJson = JSONObject.fromObject(obj);
  19. String notifyUrl = notifyJson.getString("notifyUrl");
  20. String notifyContent = notifyJson.getString("notifyContent");
  21. String result = HttpUtil.postMessage(notifyUrl, notifyContent);
  22. if (StringUtils.isBlank(result)) { // 通知失败 进入重发机制
  23. int newNotifyCount = notifyJson.getInt("notifyCount") + 1; //已经通知的次数
  24. if (newNotifyCount < 5) {
  25. notifyJson.put("notifyCount", newNotifyCount);
  26. int spacingInterval = getSpacingInterval(newNotifyCount);
  27. messageProducerService
  28. .delayMsg(notifyJson, spacingInterval);
  29. } else {
  30. logger.info("通知5次都失败,等待后台手工处理!");
  31. }
  32. }
  33. }
  34. }
  35. /**
  36. * 重复通知间隔时间(单位为秒)
  37. * @param notifyCount 已经通知的次数
  38. * @return
  39. */
  40. private int getSpacingInterval(int notifyCount) {
  41. // TODO Auto-generated method stub
  42. int spacingInterval = 0;
  43. switch (notifyCount) {
  44. case 1:
  45. spacingInterval = 10;
  46. break;
  47. case 2:
  48. spacingInterval = 20;
  49. break;
  50. case 3:
  51. spacingInterval = 30;
  52. break;
  53. case 4:
  54. spacingInterval = 60;
  55. break;
  56. case 5:
  57. spacingInterval = 90;
  58. break;
  59. default:
  60. break;
  61. }
  62. return spacingInterval;
  63. }
  64. }

Spring RabbitMQ 延迟队列的更多相关文章

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

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

  2. RabbitMQ延迟队列

    rabbitmq延迟队列 rabbitmq实现延迟队列用了rabbitmq-delayed-message-exchange插件,需要提前安装,并启用. 原理 其原理是通过Exchange来实现延迟功 ...

  3. RabbitMQ延迟队列插件安装

    RabbitMQ延迟队列插件安装 一.下载插件 下载地址:https://www.rabbitmq.com/community-plugins.html 二.把下载的插件放到指定位置 下载的文件为zi ...

  4. Spring Boot (26) RabbitMQ延迟队列

    延迟消息就是指当消息被发送以后,并不想让消费者立即拿到消息,而是等待指定时间后,消费者才拿到这个消息进行消费. 延迟队列 订单业务: 在电商/点餐中,都有下单后30分钟内没有付款,就自动取消订单. 短 ...

  5. Spring Boot(十四)RabbitMQ延迟队列

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

  6. rabbitmq延迟队列demo

    1. demo详解 1.1 工程结构: 1.2 pom 定义jar包依赖的版本.版本很重要,rabbit依赖spring,两者必须相一致,否则报错: <properties> <sp ...

  7. RabbitMQ 延迟队列,消息延迟推送

    目录 应用场景 消息延迟推送的实现 测试结果 应用场景 目前常见的应用软件都有消息的延迟推送的影子,应用也极为广泛,例如: 淘宝七天自动确认收货.在我们签收商品后,物流系统会在七天后延时发送一个消息给 ...

  8. SpringBoot RabbitMQ 延迟队列代码实现

    场景 用户下单后,如果30min未支付,则删除该订单,这时候就要可以用延迟队列 准备 利用rabbitmq_delayed_message_exchange插件: 首先下载该插件:https://ww ...

  9. C#实现rabbitmq 延迟队列功能

    最近在研究rabbitmq,项目中有这样一个场景:在用户要支付订单的时候,如果超过30分钟未支付,会把订单关掉.当然我们可以做一个定时任务,每个一段时间来扫描未支付的订单,如果该订单超过支付时间就关闭 ...

随机推荐

  1. UI设计心得

    旁观型ui.追求一种无所不在,同时低调退隐的,奢华的存在感.内容由用户自己去搜索,浏览,构建,召唤,或是随着信息世界的某种外界趋势自然产生,ui作为始终凌驾于用户之上的高高在上的守护神,随时起到中承, ...

  2. visual leak detector用法

    百度vld和windbg安装 配置symbol路径 配置环境变量 _NT_SYMBOL_PATH SRV*E:\symbols*http://msdl.microsoft.com/download/s ...

  3. JavaScript-Tool:Numeral.js

    ylbtech-JavaScript-Tool:Numeral.js A javascript library for formatting and manipulating numbers. 1. ...

  4. unbound域名解析

    安装unbound服务 # yum install unbound -y 开启服务 linux系统如何查看命令属于哪一个安装包 # yum provides */netstat 安装netstat命令 ...

  5. linux查看某个目录下有哪些文件的命令

    分别是ll和ls命令 ll /usr/local/lib ls /usr/local/lib

  6. 自己写的jQuery放大镜插件效果(二)(采用只有一张图片的思路)

    废话不多说,先看效果图,和上一章节用的是同一个小图片: 这个方法实现的放大有个弊端就是放大倍数设置的过大的话,会带来图片上的模糊.但是图片加载的话要比使用2张图片加载的快很多 插件代码: ; (fun ...

  7. Hibernate 一对多/多对多

    一对多关联(多对一): 一对多关联映射: 在多的一端添加一个外键指向一的一端,它维护的关系是一指向多 多对一关联映射: 咋多的一端加入一个外键指向一的一端,它维护的关系是多指向一 在配置文件中添加: ...

  8. Centos7扩展磁盘空间(LVM管理)

    vmware或hyperv,扩容磁盘,本例中使用的是vmware,关闭系统,在vmware—>设置—>硬盘—>扩展—>输入数字大于当前系统内存—>点击扩展,如图: 1.  ...

  9. IO流程及优化

    http://blog.csdn.net/xypzwl/article/details/51416883 一.存储设备的存储原理 机械硬盘: 机械硬盘使用磁性物质作为存储介质,用N.S极性来代表0或1 ...

  10. 解决 php 报错 open_basedir restriction in effect或者nginx提示No input file specified怎么办

    解决 php 报错 open_basedir restriction in effect或者nginx提示No input file specified怎么办 问题是出现在了PHP.INI上面了 ,原 ...