RabbitMQ的基本使用、ACK确认机制这里就不赘述了,这里主要是想实现一个应用场景:

消息消费失败后重试至多三次,仍失败则加入死信队列

一、重试机制

首先说一下RabbitMQ的消息重试机制,顾名思义,就是消息消费失败后进行重试,重试机制的触发条件是消费者显式的抛出异常,这个很类似@Transactional,如果没有显式地抛出异常或者try catch起来没有手动回滚,事务是不会回滚的。

以下代码可以触发重试机制

还有一种情况就是消息被拒绝后重新加入队列,比如basic.reject和basic.nack,并且requeue = true但是个人认为这个不算是触发了重试机制,这个是重新进入到了消息队列然后重新被消费,并且也不会触发我们重试机制的配置(如重试间隔、最大重试次数等等)。

重试机制是默认开启的,但是如果没有重试机制相关的配置会导致消息一直无间隔的重试,直到消费成功,所以要使用重试机制一定要有相关配置。

spring:rabbitmq:host: 127.0.0.1port: 5672virtual-host: mq-testusername: ********password: ********listener:simple:# ACK模式(none,auto,manual,默认为auto)acknowledge-mode: auto# 开启重试retry:# 是否开启重试机制enabled: true# 最大重试次数max-attempts: 5# 重试间隔(ms)initial-interval: 5000

二、死信队列

说到死信队列,首先需要知道什么是死信

死信就是消息在特定场景下的一种表现形式,这些场景包括:

  • 消息被拒绝(basic.reject / basic.nack),并且requeue = false
  •   消息的 TTL 过期时
  •   消息队列达到最大长度
  •   达到最大重试限制

消息在这些场景中时,被称为死信

死信队列就是用于储存死信的消息队列,在死信队列中,有且只有死信构成,不会存在其余类型的消息。死信队列也是一个普通队列,也可以被消费者消费,区别在于业务队列需要绑定在死信队列上,才能正常地把死信发送到死信队列上。

业务队列绑定死信队列

三、重试+死信的实现

文章开头的场景有两种方案可以实现

        方案一:使用自动ACK + RabbitMQ重试机制

        方案二:使用手动ACK + 手动重试机制

3.1 自动ACK + RabbitMQ重试机制

配置

spring:rabbitmq:host: 127.0.0.1port: 5672virtual-host: mq-testusername: ********password: ********listener:simple:# ACK模式(默认为auto)acknowledge-mode: auto# 开启重试retry:enabled: truemax-attempts: 5initial-interval: 5000

消费者

   @RabbitListener(queues = RabbitMqConfig.USER_ADD_QUEUE, concurrency = "10")public void userAddReceiver(String data, Message message, Channel channel) throws Exception {UserVo vo = OBJECT_MAPPER.readValue(data, UserVo.class);boolean success = messageHandle(vo);// 通过业务控制是否消费成功,消费失败则抛出异常触发重试if (!success) {log.error("消费失败");throw new Exception("消息消费失败");}}

需要说明的是,上述的方法一定要开启自动ACK,才会在到达最大重试上限后发送到死信队列,而且在重试过程中会独占当前线程,如果是单线程的消费者会导致其他消息阻塞,直至重试完成,所以可以使用@RabbitListener上的concurrency属性来控制并发数量。

3.2 手动ACK + 手动重试

配置

spring:rabbitmq:host: 127.0.0.1port: 5672virtual-host: mq-testusername: ********password: ********listener:simple:# ACK模式(默认为auto)acknowledge-mode: manual

需要说明的是,如果是手动ACK配置了重试机制,在抛出异常的时候仍会触发重试,但是达到重试上限之后,会永远处于Unacked状态,不会进入到死信队列,必须要手动拒绝才可以进入死信队列,所以说这里不用配置重试机制而是采用手动重试的方式

消费者

/*** 消息最大重试次数*/
private static final int MAX_RETRIES = 3;/*** 重试间隔(秒)*/
private static final long RETRY_INTERVAL = 5;private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();@RabbitListener(queues = RabbitMqConfig.USER_ADD_QUEUE, concurrency = "10")
public void userAddReceiver(String data, Message message, Channel channel) throws IOException, InterruptedException {UserVo vo = OBJECT_MAPPER.readValue(data, UserVo.class);// 重试次数int retryCount = 0;boolean success = false;// 消费失败并且重试次数<=重试上限次数while (!success && retryCount < MAX_RETRIES) {retryCount++;// 具体业务逻辑success = messageHandle(vo);// 如果失败则重试if (!success) {String errorTip = "第" + retryCount + "次消费失败" +((retryCount < 3) ? "," + RETRY_INTERVAL + "s后重试" : ",进入死信队列");log.error(errorTip);Thread.sleep(RETRY_INTERVAL * 1000);}}if (success) {// 消费成功,确认channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);log.info("创建订单数据消费成功");} else {// 重试多次之后仍失败,进入死信队列channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);log.info("创建订单数据消费失败");}
}

总结:两种方案都可以达到我们的预期效果,相比起来方案一会更加的方便简洁,方案二的可控性更高

RabbitMQ重试机制+死信队列相关推荐

  1. Apache Kafka-消费端消费重试和死信队列

    文章目录 概述 Code POM依赖 配置文件 配置类 SeekToCurrentErrorHandler 自定义逻辑处理消费异常 生产者 消费者 单元测试 测速结果 源码地址 概述 Spring-K ...

  2. 6.RokcketMQ消息重试与死信队列

    消息发送重试机制 Producer对发送失败的消息进行重新发送的机制,称为消息发送重试机制,也称为消息重投机制. 对于消息重投,需要注意以下几点: 生产者在发送消息时,若采用同步或异步发送方式,发送失 ...

  3. RabbitMQ重试机制

    1.RabbitMQ重试机制的简介 RabbitMQ 不会为未确认的消息设置过期时间,它判断此消息是否需要重新投递给消费者的唯一依据是消费该消息连接是否已经断开,这个设置的原因是 RabbitMQ 允 ...

  4. RabbitMQ高级特性——死信队列DLX以及代码测试

    大伙可以到我的RabbitMQ专栏获取更多信息 demo示例这里拿 概述 死信队列,缩写DLX(dead letter exchange 死信交换机),当消息称为dead message之后,会被重新 ...

  5. spring boot + rabbitMq整合之死信队列(DL)

    rabbit mq 死信队列 什么是死信队列? DL-Dead Letter 死信队列 死信,在官网中对应的单词为"Dead Letter",可以看出翻译确实非常的简单粗暴.那么死 ...

  6. RabbitMQ的TTL+死信队列 看完这篇包会!!!

    这里写目录标题 一:TTL队列过期时间设置 二:TTL消息过期时间设置 三:死信队列 - 第一种是声明队列的时候,在队列的属性中设置,这样该队列中的消息都会有相同的有效期: -第二种是发送消息时给消息 ...

  7. RabbitMQ TTL、死信队列在订单支付场景的应用

    基于RabbitMQ的TTL以及死信队列,使用SpringBoot实现延迟付款,手动补偿操作. 1.用户下单后展示等待付款页面 2.在页面上点击付款的按钮,如果不超时,则跳转到付款成功页面 3.如果超 ...

  8. Rabbitmq消费失败死信队列

    为什么80%的码农都做不了架构师?>>>    Rabbitmq 重消费处理 一 处理流程图:    业务交换机:正常接收发送者,发送过来的消息,交换机类型topic AE交换机: ...

  9. Rabbitmq死信队列

    目录 1.什么是死信队列 2.产生死信队列的原因 3.代码实现---直连交换机 3.1.导入依赖 3.2.配置rabbitmq连接信息 3.3.编写配置类 3.4.编写生产者 3.5.编写消费者 3. ...

最新文章

  1. Linux下实现apache代理tomcat
  2. [置顶] Linux协议栈代码阅读笔记(一)
  3. C语言/C++中怎么表示8进制数或者16进制数?(8进制数用数字0开头,16进制数用0x或者0X开头)
  4. [UWP小白日记-1]判断APP是否是第一次运行初始化SQLITE数据库
  5. r语言清除变量_R语言(1)初识与数据结构
  6. Java黑皮书课后题第3章:**3.22(几何:点是否在圆内)编写程序,提示用户输入一个点(x,y),然后检查这个点是否在以(0,0)为圆心、半径为10的圆内
  7. python traceback 丢失_基于python traceback实现异常的获取与处理
  8. redhat linux手动RPM安装gcc,g++
  9. Java程序编程题作业-练习-Java编程题_一球从 100 米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在 第 10 次落地时
  10. Pyltp的安装使用笔记
  11. ps2无线手柄连接arduino的使用方法
  12. 星星之火-7:从数值空间理解模拟信号、离散信号、数字信号的区别
  13. 【Java系列】:异常-Exception
  14. 树枝学术 | 图书查找、论文查找全攻略
  15. 亚马逊、速卖通、东南亚等跨境电商平台2022年最新测评自养号系统
  16. IE自动化(易语言填表原理分析)
  17. 电子垃圾绿色回收之路怎么走?
  18. 如何找出1-100之间的质数
  19. SpringBoot 整合 EasyExcel 数据写入Excel 合并单元格
  20. 五、WIN10模拟DOS环境之8086汇编实战

热门文章

  1. 【HBase】热点现象及 RowKey 设计(转)
  2. 【锐捷路由】静态路由配置
  3. 如何查询某个会议或者期刊是否被EI收录
  4. Linux字符驱动开发
  5. 通过矩阵研究二次函数(方程)-----理解二次型
  6. 教你3行Python代码,识别图片中的任意语言文字
  7. 拿到offer提出离职,公司拖30天才放人,但下家公司等不了30天,怎么办?
  8. 公共基础知识:生活常识之垃圾分类
  9. PHP 开源工作流引擎 Tpflow V6.0.2 正式版发布
  10. esp8266 继电器接线图_[ESP8266]ESP8266 NodeMCU+电磁继电器 简易物联网控制 详细制作过程...