RabbitMQ中重试机制的坑
当我们消息消费失败的时候,可以进行重试,虽然SpringAMQP集成了retry机制,但是发现使用过程有点坑,等会细说
重试机制使用场景:
1.如果是业务代码,比如空指针之类的异常那重试机制其实没什么用
2.如果是调用第三方系统,网络抖动之类的那重试机制就有用
配置使用重试机制
spring.rabbitmq.listener.simple.retry.enabled=true 是否开启消费者重试(为false时重试不生效)
spring.rabbitmq.listener.simple.retry.max-attempts=3 最大重试次数(包含本身消费的1次)
spring.rabbitmq.listener.simple.retry.initial-interval=5000 重试间隔时间(单位毫秒)
spring.rabbitmq.listener.simple.default-requeue-rejected=false 重试次数超过上面的设置之后是否丢弃(false不丢弃时需要写相应代码将该消息加入死信队列)
坑的地方来了:
不管消息被消费了之后是手动确认还是自动确认,代码中不能使用try/catch捕获异常,否则重试机制失效
所以这里要使用重试机制就有2种情况了:
1.如果消息是自动确认,由于异常,多次重试还是失败,消息被自动确认,那消息就丢失了
2.如果消息是手动确认,由于异常,多次重试还是失败,消息没被确认,也无法nack,就一直是unacked状态,导致消息积压
第一种情况代码:
@RabbitListener(queues = "order-queue")public void processOrder(Message message, Channel channel, Map map) throws Exception {System.out.println("收到订单队列消息:" + message.toString());//产生异常,导致订单处理失败throw new Exception();}
可以看到重试了3次,但是最终还是失败了,消息被自动确认了,丢失了,如果是涉及到金钱之类的就惨了。
第二种情况代码:
@RabbitListener(queues = "order-queue")public void processOrder(Message message, Channel channel, Map map) throws Exception {System.out.println("收到订单队列消息:" + message.toString());//产生异常,导致订单处理失败int a = 1/0;//确认消息channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);}
同样是重试三次之后,还是失败
这里可以看到消息会一直是unacked的状态,因为异常无法ack,然后代码中也无法nack
如何既保证重试又能不丢失消息呢?这只是我的构思:
首先是手动确认,然后在catch中throw异常触发重试机制,然后定义一个局部变量错误次数retryCount,失败后++,当retryCount=重试次数,则nack并且requeue=false到死信队列中进行入库操作,方便后续人工补偿。
//重试次数private int retryCount = 0;@RabbitListener(queues = "dead-queue")public void process(Message message, Channel channel, Map map) throws IOException {System.out.println("收到进入死信队列消息:" + message.toString());System.out.println("消息入库,后续补偿");//确认消息channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);}@RabbitListener(queues = "order-queue")public void processOrder(Message message, Channel channel, Map map) throws Exception {try {System.out.println("收到订单队列消息:" + message.toString());int a = 1 / 0;//确认消息channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);} catch (Exception e) {retryCount++;//重新抛出异常 触发重试机制throw e;} finally {//重试次数达到限制if (retryCount == 3) {System.out.println("处理订单消息异常,nack消息到死信队列");//不重新入队,发送到死信队列channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);}}}
可以看到重试3次之后,进入死信队列中。
RabbitMQ中重试机制的坑相关推荐
- RabbitMQ中的消息确认ACK机制
我们将消息持久化后,假如消费端出现异常,rabbitmq服务器会将消息缓存到内存,当生产者发送一直发送消息而消费者都没有正常消费时消息就会将这些消息全部保存在内存,当我们的消息过多时,就可能导致rab ...
- RabbitMQ重试机制+死信队列
RabbitMQ的基本使用.ACK确认机制这里就不赘述了,这里主要是想实现一个应用场景: 消息消费失败后重试至多三次,仍失败则加入死信队列 一.重试机制 首先说一下RabbitMQ的消息重试机制,顾名 ...
- RabbitMQ之消息重试机制
1.消息重试机制 消费者消费消息的时候,发生异常情况,导致消息未确认,该消息会被重复消费(默认没有重复次数,即无限循环消费),但可以通过设置重试次数以及达到重试次数之后的消息处理 spring:rab ...
- RabbitMQ重试机制
1.RabbitMQ重试机制的简介 RabbitMQ 不会为未确认的消息设置过期时间,它判断此消息是否需要重新投递给消费者的唯一依据是消费该消息连接是否已经断开,这个设置的原因是 RabbitMQ 允 ...
- rabbitmq可靠发送的自动重试机制
rabbitmq可靠发送的自动重试机制 转载地址:http://www.jianshu.com/p/6579e48d18ae http://www.jianshu.com/p/4112d78a8753 ...
- RabbitMQ中RPC的实现及其通信机制
RabbitMQ中RPC的实现:客户端发送请求消息,服务端回复响应消息,为了接受响应response,客户端需要发送一个回调队列的地址来接受响应,每条消息在发送的时候会带上一个唯一的correlati ...
- RabbitMQ中的cluster、mirrored queue,以及 warrens机制、RAM node、disk node及vhost介绍
1.RAM node和disk node的区别? RAM node仅将fabric(即queue.exchange和binding等RabbitMQ基础构件)相关元数据保存到内存中,但disk nod ...
- java中的失败重试机制总结
应用中需要实现一个功能: 需要将数据上传到远程存储服务,同时在返回处理成功情况下做其他操作.这个功能不复杂,分为两个步骤:第一步调用远程的Rest服务上传数据后对返回的结果进行处理:第二步拿到第一步结 ...
- (转)rabbitmq可靠发送的自动重试机制
转自:https://www.jianshu.com/p/6579e48d18ae rabbitTemplate的发送流程是这样的: 1 发送数据并返回(不确认rabbitmq服务器已成功接收) 2 ...
最新文章
- 我的MYSQL学习心得(六) 函数
- 【HM】第3课:JavaScript高级
- opencv线结构光三维重建
- ASP.NET中application对象的用法(面试题)
- 一键清除Delphi中无用的文件
- C++图解前缀树(字典树)
- 2012年终总结 二
- SpringCloud Alibaba Sentinel 项目基础环境搭建
- 画圆角 - HTML5 Canvas 作图
- Wannafly 每日一题 2016-12-26 KAOS 字典树
- HFSS - GSM 900 单频PIFA天线的设计与仿真
- win10 android 手机驱动下载,小米手机驱动win10驱动
- mysql truncate语句_MySQL truncate table语句
- app逆向案例分析-极速抖音
- 层次分析法(AHP)模型的应用案例
- Tackling the Qubit Mapping Problem for NISQ-Era Quantum Devices
- 几个创业小故事的启示
- 2020年三月计算机二级甘肃报名官网,2020年3月甘肃计算机二级考试报名时间
- Oracle 字段自增
- 一维谐振子定态 Schrödinger 方程的数值解法
热门文章
- SPL 工业智能:识别指定工况
- okhttp的应用详解与源码解析--http的发展史
- [RK3288][Android5.1] 移植笔记 --- gsl3673 触控驱动
- 全国人工智能师资培训高校行重磅启动,飞桨携手7校开启AI学习之旅
- Linux下查看某一进程所占用内存的方法 -- from cnblogser 小得盈满
- GitHub 上 1400星的 Git 魔法书火了
- 运行官方byfn.sh跑通网络
- Leetcode 组合总和问题
- 在 SAP BTP 上体验 SAP HANA Cloud 试用版本
- oracle 口令修改,Oracle更改口令