一、延迟队列:

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

需求:

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. ES5的继承语法

    <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8 ...

  2. npm包管理器 切换npm源 使用nrm来管理npm镜像源

    npm是NodeJs项目模块管理工具,它已经集成了nodejs安装包中,在npm从从5.2版开始,增加了 npx 命令(解决的主要问题,就是调用项目内部安装的模块,很多工具不再需要npm -g 全局来 ...

  3. 极限科技(INFINI labs)荣获中国信通院大数据“星河”标杆案例

    12 月 6 日,由中国信息通信研究院和中国通信标准化协会大数据技术标准推进委员会(CCSA TC601)共同组织的 2023 大数据"星河(Galaxy)"案例评选结果正式公示. ...

  4. OpenSSL生成加密证书.cer和.pfx

    linux自带openssl,所以在linux平台操作. 先输入: openssl 再输入: genrsa -out private-rsa.key 1024 生成私钥,无密码保护的私钥. 输入: r ...

  5. org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available es端口号及集群名称

    org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are availa ...

  6. zRAM内存压缩技术原理与应用

    zRAM内存压缩技术原理与应用 作者: 发布于:2020-3-8 8:38 分类:内存管理 http://www.wowotech.net/memory_management/458.html/com ...

  7. 《Programming from the Ground Up》阅读笔记:p1-p18

    <Programming from the Ground Up>学习第1天,p1-18总结,总计18页. 一.技术总结 1.fetch-execute cycle p9, The CPU ...

  8. AI Agent实战:智能检索在Kingbase数据库管理中的优势应用

    前言 在信息技术飞速发展的今天,数据库管理已成为IT专业人员日常工作中不可或缺的一部分.然而,面对复杂的SQL问题,传统的web搜索往往难以提供精准的答案,尤其是在针对特定数据库系统,如金仓数据库时, ...

  9. GraqphQL 学习

    GraphQL是Graph+QL.Graph是图,描述数据最好的方式是图数据结构(包括树),数据和数据之间,有像图一样的联系,以图的思维来考虑数据.QL是query language,像写query语 ...

  10. Linux Shell 常用命令 - 02篇

    系列文章: Linux Shell 常用命令 - 01篇 8. shell 中各种括号的作用 参考 https://www.jb51.net/article/123081.htm https://ww ...