应用场景

目前常见的应用软件都有消息的延迟推送的影子,应用也极为广泛,例如:

  • 淘宝七天自动确认收货。在我们签收商品后,物流系统会在七天后延时发送一个消息给支付系统,通知支付系统将款打给商家,这个过程持续七天,就是使用了消息中间件的延迟推送功能。
  • 12306 购票支付确认页面。我们在选好票点击确定跳转的页面中往往都会有倒计时,代表着 30 分钟内订单不确认的话将会自动取消订单。其实在下订单那一刻开始购票业务系统就会发送一个延时消息给订单系统,延时30分钟,告诉订单系统订单未完成,如果我们在30分钟内完成了订单,则可以通过逻辑代码判断来忽略掉收到的消息。

在上面两种场景中,如果我们使用下面两种传统解决方案无疑大大降低了系统的整体性能和吞吐量:

  • 使用 redis 给订单设置过期时间,最后通过判断 redis 中是否还有该订单来决定订单是否已经完成。这种解决方案相较于消息的延迟推送性能较低,因为我们知道 redis 都是存储于内存中,我们遇到恶意下单或者刷单的将会给内存带来巨大压力。
  • 使用传统的数据库轮询来判断数据库表中订单的状态,这无疑增加了IO次数,性能极低。
  • 使用 jvm 原生的 DelayQueue ,也是大量占用内存,而且没有持久化策略,系统宕机或者重启都会丢失订单信息。

消息延时推送实现

在 RabbitMQ 3.6.x 之前我们一般采用死信队列+TTL过期时间来实现延迟队列。

在 RabbitMQ 3.6.x 开始,RabbitMQ 官方提供了延迟队列的插件,可以下载放置到 RabbitMQ 根目录下的 plugins 下

资源地址:https://www.rabbitmq.com/community-plugins.html

我这边是在windows下,下载解压放如plugin,然后cmd:

D:\Program Files\RabbitMQ Server\rabbitmq_server-3.7.9\sbin>rabbitmq-plugins enable rabbitmq_delayed_message_exchange

代码样例

  /**
* 延时Queue
*/
public static final String DELAY_QUEUE = "delay.queue"; @Bean
public Queue delayQueue(){
return new Queue(DELAY_QUEUE, true);
} @Bean
TopicExchange delayExchange() {
Map<String, Object> pros = new HashMap<String, Object>();
//设置交换机支持延迟消息推送
pros.put("x-delayed-message", "topic");
TopicExchange delayTopicExchange = new TopicExchange("delayTopicExchange",true,false,pros); delayTopicExchange.setDelayed(true);
return delayTopicExchange;
} @Bean
Binding bindingDelayExchange(Queue delayQueue, TopicExchange delayExchange) {
return BindingBuilder.bind(delayQueue).to(delayExchange).with("delay.#");
}

生产者:

 public void delaySend() throws IOException {
User user = new User();
user.setUserName("Sender1.....");
user.setMobile("6666666");
byte[] body = Base64Utils.obj2byte(user); Message message = new Message(body,new MessageProperties()); //延时插件https://www.rabbitmq.com/community-plugins.html
//然后放plugin包
//启用插件:rabbitmq-plugins enable rabbitmq_delayed_message_exchange
//Lambda表达式
MessagePostProcessor messagePostProcessor = message1 -> {
//设置消息持久化
message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
message.getMessageProperties().setHeader("x-delay", 10000);
//message.getMessageProperties().setDelay(20000);
return message;
}; System.out.println("发送演示消息>>>>>"+new Date());
rabbitTemplate.convertAndSend("delayTopicExchange","delay.message",message,messagePostProcessor);
}

rabbitTemplate 通常在SpringBoot 中默认配置

测试用例:

   @Test
public void send6() throws Exception {
topicSender.delaySend();
}

运行下:

消费端(另一工程):

 /**
* 延时Queue
*/
public static final String DELAY_QUEUE = "delay.queue";
package com.example.demo.rabbitMq.exchange.topic;

import com.example.demo.utils.Base64Utils;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component; import java.io.IOException;
import java.util.Date; @Component
public class TopicReceiver6 { private Logger logger = LoggerFactory.getLogger(this.getClass()); @RabbitListener(queues = TopicRabbitConstant.DELAY_QUEUE)
public void process(Message message, Channel channel) throws IOException {
try {
System.out.println("Receiver6 : " + new Date() + ">>>>" + Base64Utils.byteToObj(message.getBody())); } catch (Exception e) {
logger.error("接收失败",e);
}
}
}

整体测试验证

1、启动消费端

2、生产者发送消息

结果:

生产者工程Console:

消费这边工程Console:

时间间隔10s

参考:

https://www.cnblogs.com/haixiang/p/10966985.html

RabbitMq(7)消息延时推送的更多相关文章

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

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

  2. #研发中间件介绍#异步消息可靠推送Notify

    郑昀 基于朱传志的设计文档 最后更新于2014/11/11 关键词:异步消息.订阅者集群.可伸缩.Push模式.Pull模式 本文档适用人员:研发   电商系统为什么需要 NotifyServer? ...

  3. PHP版微信公共平台消息主动推送,突破订阅号一天只能发送一条信息限制

    2013年10月06日最新整理. PHP版微信公共平台消息主动推送,突破订阅号一天只能发送一条信息限制 微信公共平台消息主动推送接口一直是腾讯的私用接口,相信很多朋友都非常想要用到这个功能. 通过学习 ...

  4. Swift - 本地消息的推送通知(附样例)

    使用UILocalNotification可以很方便的实现消息的推送功能.我们可以设置这个消息的推送时间,推送内容等. 当推送时间一到,不管用户在桌面还是其他应用中,屏幕上方会都显示出推送消息. 1, ...

  5. .NET之微信消息模板推送

    最近在项目中使用到了微信消息模板推送的功能,也就是将对应的消息推送到对应的用户微信上去,前提是你必须要有一个微信公众号并且是付费了的才会有这个功能,还有就是要推送的用户必须是的关注了你的微信公众号的. ...

  6. dwr3实现消息精确推送详细步骤

    最近项目中需要用到推送消息,找了很久终于找到一篇不错的文章,方便以后查看就转载了,也分享给大家,希望能帮到有需要的人. 第一.在项目中引入dwr.jar,然后在web.xml中进行配置,配置如下: & ...

  7. 基于HTTP协议之WEB消息实时推送技术原理及实现

    很早就想写一些关于网页消息实时推送技术方面的文章,但是由于最近实在忙,没有时间去写文章.本文主要讲解基于 HTTP1.1 协议的 WEB 推送的技术原理及实现.本人曾经在工作的时候也有做过一些用到网页 ...

  8. NET SignaiR 实现消息的推送,并使用Push.js实现通知

    一.使用背景 1. SignalR是什么? ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程.实时 Web 功能是指 ...

  9. spring boot 集成 websocket 实现消息主动推送

    spring boot 集成 websocket 实现消息主动 前言 http协议是无状态协议,每次请求都不知道前面发生了什么,而且只可以由浏览器端请求服务器端,而不能由服务器去主动通知浏览器端,是单 ...

随机推荐

  1. HTML: 引号不能忽视

    在js中常常生成拼接html,然后放到dom中,但是有些拼接的html标签需要加一些指或者属性,这个时候不能忽略引号 如果data.link_tel有空格,不加单引号导致value的值不完全 str ...

  2. Spring MVC-学习笔记(3)参数绑定注解、HttpMessageConverter<T>信息转换、jackson、fastjson、XML

    1.参数绑定注解 1>@RequestParam: 用于将指定的请求参数赋值给方法中的指定参数.支持的属性: 2>@PathVariable:可以方便的获得URL中的动态参数,只支持一个属 ...

  3. 《剑指offer》面试题21 包含min函数的栈 Java版

    (min函数的作用是返回栈内最小值) 首先这个栈要具有普通栈所具有的push()和pop()方法,那么内部一定包含一个Stack.至于还要能实现min函数,而且还是在O(1)时间复杂度内,我们不得不考 ...

  4. Sobel硬件实现的硬件代码分析(三)

    #include "xaxivdma.h" #include "xaxivdma_i.h" #include "xhls_sobel.h" ...

  5. Dubbo学习源码总结系列四--集群容错机制

    Dubbo提供了哪些集群容错机制?如何实现的?         提供了六种集群容错机制,包括Failover(失败自动切换,尝试其他服务器).Failfast(失败立即抛出异常).Failsafe(失 ...

  6. Sass @debug

    @debug 在 Sass 中是用来调试的,当你的在 Sass 的源码中使用了 @debug 指令之后,Sass 代码在编译出错时,在命令终端会输出你设置的提示 Bug: @debug 10em + ...

  7. python的list拷贝

    有三种情况 第一种:赋值(不是拷贝) a=[1,2,3] b=a 这种不是拷贝,a和b是一个变量,内存是一个 第二种:浅拷贝 a=[1,2,3,[4,5,6]] b=a b的第一层是独立的,第二层会更 ...

  8. random模块 os模块

    # random# import random# random.random() # 大于0且小于1之间的小数# random.randint() # 大于等于1且小于等于3之间的整数# random ...

  9. django 的保护机制

  10. [洛谷P1353] 跑步Running

    问题描述 奶牛们打算通过锻炼来培养自己的运动细胞,作为其中的一员,贝茜选择的运动方式是每天进行N(1 <= N <= 10,000)分钟的晨跑.在每分钟的开始,贝茜会选择下一分钟是用来跑步 ...