Spring boot 整合 rabbit MQ 死信队列的应用-订单过期自动取消_rabbitmq 死信队列 处理订单过期未支付-程序员宅基地

技术标签: spring boot  死信队列  订单过期自动取消  rabbit mq  

用户下了订单之后,还未付款,在规定的期限内如果没有支付,则这个订单应该标记为取消。

如果实现过期自动取消,下面有几种解决方案

  1. 定时轮询订单,超过期限且未支付
  2. 创建订单后,开启一个消息队列,等待X时间后执行
  3. 通过死信队列回调

其实方案二和死信队列的原理差不多,但是MQ已经拥有类似的机制,所以我们直接沿用即可。

死信队列介绍

  • 死信队列:DLX,dead-letter-exchange
  • 利用DLX,当消息在一个队列中变成死信 (dead message) 之后,它能被重新publish到另一个Exchange,这个Exchange就是DLX

消息变成死信有以下几种情况

  • 消息被拒绝(basic.reject/ basic.nack)并且不再重新投递 requeue=false
  • 消息过期 (rabbitmq Time-To-Live -> messageProperties.setExpiration())
  • 队列超出最大长度

整体的一个流程思路:

创建一个普通的队列(加入死信队列的一些属性),这个消息永远没有人消费,没人消费则过期,过期则通过之前的设置转发回调给另外一个队列

下面是基于Spring boot 的实际用例

  1. 引入依赖
    1.  <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-amqp</artifactId>
       </dependency>

       

  2. 配置类
    1.   /**
           * 死信队列交换机标识符  属性值不能改,写死
           */
          private static final String DEAD_LETTER_QUEUE_KEY = "x-dead-letter-exchange";
          /**
           * 死信队列交换机绑定键 标识符  属性值不能改,写死
           */
          private static final String  DEAD_LETTER_ROUTING_KEY = "x-dead-letter-routing-key";
      
      
          /**
           * deadLetterExchange(direct类型交换机)
           *
           * @return
           */
          @Bean("deadLetterExchange")
          public Exchange deadLetterExchange() {
              return ExchangeBuilder.directExchange("DEAD_LETTER_EXCHANGE").durable(true).build();
          }
      
          /**
           * 声明一个死信队列
           * x-dead-letter-exchange   对应  死信交换机
           * x-dead-letter-routing-key  对应 死信队列
           */
          @Bean("deadLetterQueue")
          public Queue deadLetterQueue() {
              //应该像个普通队列,里面多设置了两个参数,这个队列没有被消费或者超时 则通过x-dead-letter-exchange 指明重新回到死信交换机 TEST_SIGN_EXCHANGE
              //交换机
              // 参数
              Map<String, Object> args = new HashMap<>(2);
              // 出现dead letter之后将dead letter重新发送到指定exchange
              args.put(DEAD_LETTER_QUEUE_KEY, "DEAD_LETTER_EXCHANGE");
              // 出现dead letter之后将dead letter重新按照指定的routing-key发送
              args.put(DEAD_LETTER_ROUTING_KEY, "REDIRECT_KEY");
              // name队列名字  durable是否持久化,true保证消息的不丢失, exclusive是否排他队列,如果一个队列被声明为排他队列,该队列仅对首次申明它的连接可见,并在连接断开时自动删除, autoDelete如果该队列没有任何订阅的消费者的话,该队列是否会被自动删除, arguments参数map
              return new Queue("DEAD_LETTER_QUEUE", true, false, false, args);
          }
      
      
          /**
           * 死信路由通过 DEAD_LETTER_KEY 绑定到死信队列上.
           */
          @Bean
          public Binding deadLetterBinding() {
              return new Binding("DEAD_LETTER_QUEUE", Binding.DestinationType.QUEUE, "DEAD_LETTER_EXCHANGE", "DEAD_LETTER_KEY", null);
      
          }
      
          /**
           * 死信路由通过 REDIRECT_KEY 绑定到转发队列上.   这个队列绑定的是当出现死信消息后 重新转发给的队列
           */
          @Bean
          public Binding redirectBinding() {
              return new Binding("REDIRECT_QUEUE", Binding.DestinationType.QUEUE, "DEAD_LETTER_EXCHANGE", "REDIRECT_KEY", null);
          }
          /**
           * 定义死信队列转发队列.   (和普通队列一样,这个队列是为了原有的消息没有被消费重新转发给一个新的队列)
           */
          @Bean("redirectQueue")
          public Queue redirectQueue() {
              return new Queue("REDIRECT_QUEUE", true, false, false);
          }
      

       

  3. 监听类
    1. @Component
      public class TestMQConsumer {
      
           /**
           * 监听转发队列  死信队列重新转发回这里
           *
           */
          @RabbitListener(queues = {"REDIRECT_QUEUE"})
          public void redirect(HashMap<String,Object> dataMap) throws IOException {
              System.out.println(dataMap.get("msg"));
              System.out.println("我是转发队列,这里执行逻辑业务");
          }
      }
      

       

  4. 执行类
    1.   @Test
          public void testMq(){
              //声明消息处理器 设置消息的编码以及消息的过期时间 时间毫秒值为字符串
              MessagePostProcessor messagePostProcessor = message -> {
                  MessageProperties messageProperties = message.getMessageProperties();
                  messageProperties.setMessageId(UUID.randomUUID().toString().replaceAll("-", ""));
                  messageProperties.setContentEncoding("utf-8");
                  //超时时间10秒
                  messageProperties.setExpiration(String.valueOf(1000*10));
                  return message;
              };
              Map<String, Object> dataMap = new HashMap<>();
              dataMap.put("msg","我是传递的消息");
              rabbitTemplate.convertAndSend("DEAD_LETTER_EXCHANGE", "DEAD_LETTER_KEY",dataMap,messagePostProcessor);
          }

       

执行效果:

DEAD_LETTER_QUEUE 执行后没有被消费,超过10秒钟后自动回调 REDIRECT_QUEUE 

继续学习呀!!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/p_moriarty/article/details/102218596

智能推荐

三、购物车案例_17(笔记)_购物车案例请求数据地址-程序员宅基地

文章浏览阅读332次。购物车_购物车案例请求数据地址

在unity中DOTween 使用方法_tween number-程序员宅基地

文章浏览阅读603次。DOTween 使用方法_tween number

DSP之TMS320F28335学习总结与笔记(二)————ADC模块_dsp2833x_adc.c-程序员宅基地

文章浏览阅读1.2w次,点赞13次,收藏138次。F28335 ADC模块ADC转换模块A/D转换器(ADC)将模拟量转换为数字量通常要经过四个步骤:采样、保持、量化和编码。采样:将一个时间上连续变化的模拟量转化为时间上离散变化的模拟量。保持:将采样结果存储起来,直到下次采样,这个过程称作保持。一般,采样器和保持电路一起总称为采样保持电路。量化:将采样电平归化为与之接近的离散数字电平,这个过程称作量化。ADC关键指标分辨率:指数字量变化一个最小量时模拟信号的变化量,定义为满刻度与2^n的比值。分辨率又称为精度,通常以数字信号的位_dsp2833x_adc.c

V-rep学习笔记:机器人路径规划2-程序员宅基地

文章浏览阅读1.8k次。   路径规划问题是机器人学研究的一个重要领域,它是指给定操作环境以及起始和目标的位置姿态,要求选择一条从起始点到目标点的路径,使运动物体(移动机器人或机械臂)能安全、无碰撞地通过所有的障碍物而达到目标位置。路径规划从研究对象上可分为关节式机械臂和移动机器人。一般来讲前者具有更多的自由度,而后者的作业范围要更大一些,这两类对象具有不同的特点,因此在研究方法上略有不同。在V-rep学习笔记:机器人路..._collision pairs

问题:U8的存货同步到本地时,报“数据库可能存在相同的编码”_数据库可能已经存在相同的编码等-程序员宅基地

文章浏览阅读1.5k次。1.环境:U8与本地某程序。跨服务器、跨数据库。2.问题:U8的存货同步到本地时,报“数据库可能存在相同的编码”。3.原因:在确认了U8程序正常、本地程序正常、U8数据库正常、本地数据库正常、链接服务器正常、触发器本身正常后,回到了问题的本身:为何原来的同步执行正常,但是现在的存货保存却异常,怀疑是最新的存货有问题。所以先停了触发器,然后用U8做了一个存货,正常保存后。启用触发器,直接用刚_数据库可能已经存在相同的编码等

EOS与ESD的区别_eos和esd的区别-程序员宅基地

文章浏览阅读7.9k次。摘要:什么是EOS?EOS与ESD的区别是什么?EOS为ELectrical Over Stress的缩写,指所有的过度电性应力。当外界电流或电压超过器件的最大规范条件时,器件性能会减弱甚至损坏。一、什么是EOS?EOS为ELectrical Over Stress的缩写,指所有的过度电性应力。当外界电流或电压超过器件的最大规范条件时,器件性能会减弱甚至损坏。EOS通常产生于:1.电源(AC/DC) 干扰、电源杂讯和过电压。2.由于测试程序切换(热切换)导致的瞬变电流..._eos和esd的区别

随便推点

vue玩转移动端H5微信支付和支付宝支付_移动端支付宝微信支付vue项目怎么写-程序员宅基地

文章浏览阅读5.8k次,点赞13次,收藏57次。业务场景介绍:H5移动端支持微信支付 [ 微信支付分为微信内支付(JSAPI支付官方API)和微信外支付(H5支付官方API)] && 支付宝支付 [手机网站支付转 APP 支付 官方API ]订单生成逻辑:前端请求后端提交订单,后端去和微信或者支付宝对接生成订单(后续支付都是这个逻辑进行的对接)一、移动端微信支付,vue中如何玩?在移动端微信支付分为微信内支付和微信外支付。1.在订单组件中选择支付方式之后在支付页面先去判断是否是在微信内://判断是否微信 is__移动端支付宝微信支付vue项目怎么写

深度学习AI编译器-TVM简介_tvm编译器-程序员宅基地

文章浏览阅读2k次,点赞5次,收藏9次。深度学习编译器主要为解决不同框架下训练的模型部署到指定的某些设备上时所遇到的一系列复杂的问题,即将各种深度学习训练框架的模型部署到各种硬件所面临的问题;_tvm编译器

如何检测新移动硬盘--HD Tune Pro硬盘工具_怎么检测移动硬盘是不是新的-程序员宅基地

文章浏览阅读2.8w次,点赞7次,收藏22次。要想检测移动硬盘的读写速度和是否有坏道,可使用HD Tune Pro硬盘工具软件。除了硬盘传输速率、健康状况、温度、随机存取、磁盘错误扫描、文件基准检测等常见功能外,该软件还能检测硬盘的固件版本、序列号、容量、缓存以及当前的Ultra DMA模式等。此外,目前市场上主流的2.5英寸320GB移动硬盘的数据读取速度大多在30MB/s左右;写入速度稍微慢一点,一般在25MB/s左右。..._怎么检测移动硬盘是不是新的

POJ - 2096 Collecting Bugs_poj collecting bugs-程序员宅基地

文章浏览阅读184次。Ivan is fond of collecting. Unlike other people who collect post stamps, coins or other material stuff, he collects software bugs. When Ivan gets a new program, he classifies all possible bugs into n ..._poj collecting bugs

ESP32单片机入门篇-程序员宅基地

文章浏览阅读8.8k次,点赞11次,收藏88次。ESP32单片机是一款基于改进的Tensilica LX6微架构的32位双核处理器 SoC,配备2.4 GHz Wi-Fi和蓝牙功能。由于其低功耗、高速度和广泛的应用适用性而被广泛应用。本文将介绍ESP32单片机的基本概念,开发环境,开发语言和一些注意事项,并提供一些简单的代码例程,以点亮LED灯和控制继电器为例。_esp32

Java WEB开发基础知识-程序员宅基地

文章浏览阅读2.9w次,点赞53次,收藏319次。一、WEB应用程序B/S ( browser/server ,浏览器/服务器)架构基于HTTP传输协议(超文本传输协议,回忆HTML的名字:超文本标记语言)WEB程序必须要运行在web容器上,如Tomcat /Jboss/WebLogic等二、HTTP协议HTTP使用TCP作为它的支撑运输层协议,默认的端口是80(缺省端口)。超文本传输协议(Hypertext Transfer Protocol,..._java web开发

推荐文章

热门文章

相关标签