一、延迟队列:

消息经过交换机分配到队列上之后,在到达指定的时间,才会被消费?

需求:

1、下单之后的30分钟,用户未支付,订单取消,回滚库存

2、新用户注册7天后,发送短信慰问,或者是用户生日发送短信祝福

业务事件触发之后进入一个时间间隔,消息在这个间隔量的节点上再执行

Java程序提供了一些定时任务的框架,可以调用Java程序实现

或者是消息中间件自己做的延迟队列

是使用程序解决还是用消息队列解决,取决于现实业务的考量

二、RabbitMQ的技术方案:

RabbitMQ没有延迟队列这样的功能提供

可以使用 TTL + DLX 组合实现延迟队列的效果

三、RabbitMQ代码实现:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">
<!--加载配置文件-->
<context:property-placeholder location="classpath:rabbitmq.properties"/> <!-- 定义rabbitmq connectionFactory publisher-confirms="true" 消息发送可确认
publisher-returns="true"
-->
<rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}"
port="${rabbitmq.port}"
username="${rabbitmq.username}"
password="${rabbitmq.password}"
virtual-host="${rabbitmq.virtual-host}"
publisher-confirms="true"
publisher-returns="true"
/>
<!--定义管理交换机、队列-->
<rabbit:admin connection-factory="connectionFactory"/> <!--定义rabbitTemplate对象操作可以在代码中方便发送消息-->
<rabbit:template id="rabbitTemplate" connection-factory="connectionFactory"/> <!--
延迟队列
1、定义正常的交换机和队列
2、定义死信的交换机和队列
3、绑定,并设置正常过期时间为30分钟 delay
--> <!-- 正常 -->
<rabbit:queue id="delay-regular-Q" name="delay-regular-Q">
<rabbit:queue-arguments>
<!-- 绑定分配死信-->
<entry key="x-dead-letter-exchange" value="delay-dead-X" />
<entry key="x-dead-letter-routing-key" value="dlx.order.cancel"/> <!-- TTL超时限定 -->
<entry key="x-message-ttl" value="10000" value-type="java.lang.Integer" />
</rabbit:queue-arguments>
</rabbit:queue> <rabbit:topic-exchange name="delay-regular-X" >
<rabbit:bindings>
<rabbit:binding pattern="order.#" queue="delay-regular-Q"/>
</rabbit:bindings>
</rabbit:topic-exchange> <!-- 死信 -->
<rabbit:queue id="delay-dead-Q" name="delay-dead-Q" />
<rabbit:topic-exchange name="delay-dead-X" >
<rabbit:bindings>
<rabbit:binding pattern="dlx.order.#" queue="delay-dead-Q"/>
</rabbit:bindings>
</rabbit:topic-exchange>
</beans>

测试类编写发送一条消息:

    @Test
public void delayTest() {
//
rabbitTemplate.convertAndSend(
"delay-regular-X",
"order.info",
"延迟队列测试 。。。。 在死信队列查看此消息 ");
}

消费者服务编写延迟队列的监听器

注意这个监听器是监听死信队列的

package cn.dzz.rabbitmq.listener;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.stereotype.Component; import java.nio.charset.StandardCharsets;
@Component
public class DelayListener implements ChannelAwareMessageListener {
@Override
public void onMessage(Message message, Channel channel) throws Exception {
long deliveryTag = 0;
try { System.out.println(new String(message.getBody(), StandardCharsets.UTF_8)); // 处理业务逻辑
// todo... /**
*
* 根据接收的ID查询订单状态
* 判断状态是否为支付成功
* 判断状态是否为支付成功
* 取消订单, 回滚库存
*
*/ int i = 10 / 0; // 这个异常会被捕获,然后触发RabbitMQ一直让消息重新入列发送 // 业务签收
deliveryTag = message.getMessageProperties().getDeliveryTag(); channel.basicAck(deliveryTag, true); } catch (Exception exception) {
// exception.printStackTrace();
System.out.println("已经触发异常Catch 消息被拒绝 .... ");
channel.basicNack(deliveryTag, true, false); // 被拒绝的消息不再重回队列, 这样这个消息才会分配到死信队列中 }
}
}

监听器XML配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">
<!--加载配置文件-->
<context:property-placeholder location="classpath:rabbitmq.properties"/> <!-- 定义rabbitmq connectionFactory -->
<rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}"
port="${rabbitmq.port}"
username="${rabbitmq.username}"
password="${rabbitmq.password}"
virtual-host="${rabbitmq.virtual-host}"/> <context:component-scan base-package="cn.dzz.rabbitmq.listener" /> <!--
定义监听器容器
acknowledge="manual" 默认就是none
-->
<rabbit:listener-container connection-factory="connectionFactory" auto-declare="true" acknowledge="manual">
<rabbit:listener ref="delayListener" queue-names="delay-dead-Q" />
</rabbit:listener-container> </beans>

消费者服务经过延迟后收到消息:

监听测试
延迟队列测试 。。。。 在死信队列查看此消息
已经触发异常Catch 消息被拒绝 ....

【RabbitMQ】11 深入部分P4 延迟队列的更多相关文章

  1. 【RabbitMQ 实战指南】一 延迟队列

    1.什么是延迟队列 延迟队列中存储延迟消息,延迟消息是指当消息被发送到队列中不会立即消费,而是等待一段时间后再消费该消息. 延迟队列很多应用场景,一个典型的应用场景是订单未支付超时取消,用户下单之后3 ...

  2. RabbitMQ 入门教程(PHP版) 延迟队列,延迟任务

    延迟任务应用场景 场景一:物联网系统经常会遇到向终端下发命令,如果命令一段时间没有应答,就需要设置成超时. 场景二:订单下单之后30分钟后,如果用户没有付钱,则系统自动取消订单. 场景三:过1分钟给新 ...

  3. RabbitMQ、RocketMQ、Kafka延迟队列实现

    延迟队列在实际项目中有非常多的应用场景,最常见的比如订单未支付,超时取消订单,在创建订单的时候发送一条延迟消息,达到延迟时间之后消费者收到消息,如果订单没有支付的话,那么就取消订单. 那么,今天我们需 ...

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

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

  5. RabbitMQ如何实现延迟队列?(转)

    什么是延迟队列 延迟队列存储的对象肯定是对应的延迟消息,所谓"延迟消息"是指当消息被发送以后,并不想让消费者立即拿到消息,而是等待指定时间后,消费者才拿到这个消息进行消费. 场景一 ...

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

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

  7. rabbitmq延迟队列demo

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

  8. 【RabbitMQ】一文带你搞定RabbitMQ延迟队列

    本文口味:鱼香肉丝   预计阅读:10分钟 一.说明 在上一篇中,介绍了RabbitMQ中的死信队列是什么,何时使用以及如何使用RabbitMQ的死信队列.相信通过上一篇的学习,对于死信队列已经有了更 ...

  9. rabbitmq 实现延迟队列的两种方式

    原文地址:https://blog.csdn.net/u014308482/article/details/53036770 ps: 文章里面延迟队列=延时队列 什么是延迟队列 延迟队列存储的对象肯定 ...

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

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

随机推荐

  1. zkq 数学听课笔记

    线性代数 域 \(F\),OI 中常用的域是 \(\Z_{p^c}\). \(n\) 维向量 \(\vec x \in F^n\),其中 \(x_i \in F\),注意向量是列向量. \(F^n\) ...

  2. .net6 asp.net core mvc 中使用NLog ILogger

    1.用VS2022新建一个.NET6 MVC项目. 2.使用nuget引用NLog.Extensions.Logging. 3.项目中新建一个NLog.config配置文件,右键属性设置为" ...

  3. AIGC底层技术介绍

    1.AIGC概述 AIGC,全称Artificial Intelligence Generated Content,即人工智能生成内容.这是一种新兴的人工智能技术,其核心思想是利用人工智能模型,根据给 ...

  4. Vulnhub Mercy Walkthrough

    Recon 首先进行二层扫描. ┌──(kali㉿kali)-[~] └─$ sudo netdiscover -r 192.168.80.0/24 Currently scanning: Finis ...

  5. 基于 .NET CORE + VUE 前后端项目打包,实现批处理安装,一键部署

    2023年7月18日 目前基于已完成了基于WPF界面的全自动部署小工具 自动判断相关.net core环境和依赖,自动部署mysql数据库,自动部署前后端web服务的功能. 有疑问的可以直接评论. - ...

  6. Jenkins构建UI自动化项目,指定本地执行,没弹起浏览显示

    1. 原因分析 为什么执行web没有弹出浏览器,Jenkins日志显示正在执行中 jenkins是用windows installer 安装成 windows的服务了,那么启动windows后jenk ...

  7. Vim的移动大法

    Vim的移动大法 移动光标的按键 "h" 向左移动 "j"向下移动 "k"向上移动 "l"向右移动 在单词之间移动 注: ...

  8. opengrok源代码在线阅读平台搭建及字体修改

    服务搭建 我所编写的docker-compose.yml如下,成功运行后将源码目录移动至 /data/opengrok/src ,重启容器使得opengrok快速更新索引 services: open ...

  9. Linux设备模型:1、设计思想

    背景 搞Linux搞这么久,一直在调试各种各样的驱动.却发现对Linux驱动有太多不够了解的地方.因此转载了 蜗窝科技 的有关文章,作为学习. 内容有少量纠正,样式有做调整. 作者:wowo 发布于: ...

  10. Java助力加固Excel文件,保障数据安全

    前言 Excel文件保护是常用的一种功能,文件保护主要有三种: 添加密码,如果没有密码不允许打开文件. 添加密码,如果没有密码,不能修改文件,但可以打开,只读以及另存文件. 只读推荐,通常推荐打开Ex ...