01-Spring实现重试和降级机制
主要用于在模块调用中,出现失败、异常情况下,仍需要进行重复调用。并且在最终调用失败时,可以采用降级措施,返回一般结果。
1、重试机制
我们采用spring 提供的retry 插件,其原理采用aop机制,所以需要额外引入starter-aop包
1、依赖引入
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId>
</dependency>
2、在主启动类或者需要重试的方法所在的类上添加注解@EnableRetry
3、在需要重试的方法上增加注解 @Retryable,表示该方法需要重试。可以定义在接口的抽象方法上,也可以定义在实际的具体方法上。
public interface RetryService {/*** 指定异常CustomRetryException重试,重试最大次数为4(默认是3),重试补偿机制间隔200毫秒* 还可以配置exclude,指定异常不重试,默认为空* @return result* @throws CustomRetryException 指定异常*/@Retryable(value = {CustomRetryException.class},maxAttempts = 4,backoff = @Backoff(200))String retry() throws CustomRetryException;
}
@Retryable注解参数说明:
maxAttempts :最大重试次数,默认为3,如果要设置的重试次数为3,可以不写;
value:抛出指定异常才会重试,支持多异常
include:和value一样,默认为空,当exclude也为空时,默认所以异常
exclude:指定不处理的异常
backoff:重试等待时间策略,默认使用@Backoff的value默认为1000L,我们设置为200L。
@Backoff注解中的参数说明:
value:隔多少毫秒后重试,默认为1000L;
delay:和value一样,但是默认为0;
multiplier(指定延迟倍数)默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为1.5,则第一次重试为2秒,第二次为3秒,第三次为4.5秒。
④可以同时在同一个类中使用@Recover来处理N次处理后都没有成功后需要处理的事情
可以在指定方法上标记@Recover来开启重试失败后调用的方法(注意,需跟重处理方法在同一个类中)

2、请求降级
使用@Recover实现降级措施
当重试到达指定次数时,被注解的方法将被回调,可以在该方法中进行日志处理。需要注意的是发生的异常和入参类型一致时才会回调。
@Retryable和@Recover修饰的方法要在同一个类中,且被@Retryable 标记的方法不能有返回值,这样Recover方法才会生效。
/*** value:抛出指定异常才会重试* include:和value一样,默认为空,当exclude也为空时,默认所有异常* exclude:指定不处理的异常* maxAttempts:最大重试次数,默认3次* backoff:重试等待策略,* 默认使用@Backoff,@Backoff的value默认为1000L,我们设置为2000; 以毫秒为单位的延迟(默认 1000)* multiplier(指定延迟倍数)默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为1.5,则第一次重试为2秒,第二次为3秒,第三次为4.5秒。* @param code* @return* @throws Exception*/@Override@Retryable(value = Exception.class,maxAttempts = 3,backoff = @Backoff(delay = 2000,multiplier = 1.5))public int testRetry(int code) throws Exception{System.out.println("test被调用,时间:"+ LocalTime.now());if (code==0){throw new Exception("情况不对头!");}System.out.println("test被调用,情况对头了!");return 200;} /*** Spring-Retry还提供了@Recover注解,用于@Retryable重试失败后处理方法。* 如果不需要回调方法,可以直接不写回调方法,那么实现的效果是,重试次数完了后,如果还是没成功没符合业务判断,就抛出异常。* 可以看到传参里面写的是 Exception e,这个是作为回调的接头暗号(重试次数用完了,还是失败,我们抛出这个Exception e通知触发这个回调方法)。* 注意事项:* 方法的返回值必须与@Retryable方法一致* 方法的第一个参数,必须是Throwable类型的,建议是与@Retryable配置的异常一致,其他的参数,需要哪个参数,写进去就可以了(@Recover方法中有的)* 该回调方法与重试方法写在同一个实现类里面** 由于是基于AOP实现,所以不支持类里自调用方法* 如果重试失败需要给@Recover注解的方法做后续处理,那这个重试的方法不能有返回值,只能是void* 方法内不能使用try catch,只能往外抛异常* @Recover注解来开启重试失败后调用的方法(注意,需跟重处理方法在同一个类中),此注解注释的方法参数一定要是@Retryable抛出的异常,否则无法识别,可以在该方法中进行日志处理。* @param e* @param code* @return*/@Recoverpublic int recover(Exception e, int code){System.out.println("回调方法执行!!!!");//记日志到数据库 或者调用其余的方法System.out.println("异常信息:"+e.getMessage());return 400;}
3、 RetryTemplate
对每个方法上进行注解定义以及对应降低方法定义,过于繁琐。
spring 提供 retryTemplate 的bean对象,定义一个可重试、降级的代理对象。
RetryTemplate提供了RetryOperations的一种具体实现。它被认为是从中创建bean的良好做法。
1、定义retryTemplate对象
@Bean@ConditionalOnMissingBeanpublic RetryTemplate retryTemplate(){final SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy();simpleRetryPolicy.setMaxAttempts(4);
final FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();fixedBackOffPolicy.setBackOffPeriod(1000L);
return RetryTemplate.builder().customPolicy(simpleRetryPolicy).customBackoff(fixedBackOffPolicy).retryOn(CustomRetryException.class).build();}
2、使用retryTemplate
@Autowiredpivate RetryTemplate retryTemplate;
@Testvoid retryWithoutAnnotation(){try {String message = retryTemplate.execute(x -> retryService.retryWithoutAnnotation());log.info("message = "+message);} catch (CustomRetryException e) {log.error("Error while executing test {}",e.getMessage());}}
3、RecoveryCallback 降级
execute时,可以选择输入RecoveryCallback回调,确定重试结束后,仍然出现异常的recovery行为。自定义方法如下:
@Slf4j
public class CustomRecoveryCallback implements RecoveryCallback<String> {
@Overridepublic String recover(RetryContext retryContext) throws Exception {log.info("Default Retry service test,total retry {}",retryContext.getRetryCount());return "Error Class :: " + retryContext.getLastThrowable().getClass().getName();}
}
4、RetryListenerSupport生命周期控制
如果我们想在重试整个生命周期中,按照不同的阶段设置一些事件监听处理机制,那怎么办呢?设置自定义的RetryListenerSupport能帮助到我们。我们继承RetryListenerSupport,并重新Override close 、onError、open方法,这三个方法分别表示
- 所有重试结束时 close
- 每一次重试发生异常时 onError
- 重试正式开始前 open
@Slf4j
public class DefaultListenerSupport extends RetryListenerSupport {
@Overridepublic <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {log.info("DefaultListenerSupport close");super.close(context, callback, throwable);}
@Overridepublic <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {log.info("DefaultListenerSupport onError");super.onError(context, callback, throwable);}
@Overridepublic <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {log.info("DefaultListenerSupport open");return super.open(context, callback);}
}
并且在构造RetryTemaplate时候,设置withListener字段。
@Bean
@ConditionalOnMissingBean
public RetryListenerSupport retryListenerSupport(){return new DefaultListenerSupport();
}
@Bean
@ConditionalOnMissingBean
public RetryTemplate retryTemplate(RetryListenerSupport retryListenerSupport){
...return RetryTemplate.builder().customPolicy(simpleRetryPolicy).customBackoff(fixedBackOffPolicy).withListener(retryListenerSupport).retryOn(CustomRetryException.class).build();
}
相关文章:
01-Spring实现重试和降级机制
主要用于在模块调用中,出现失败、异常情况下,仍需要进行重复调用。并且在最终调用失败时,可以采用降级措施,返回一般结果。 1、重试机制 我们采用spring 提供的retry 插件,其原理采用aop机制,所以需要额外…...
docker部署showdoc
目录 安装 1.拉取镜像 2.创建容器 使用 1.选择语言 2.默认账户/密码:showdoc/123456编辑 3.登陆 4.首页 安装 1.拉取镜像 docker pull star7th/showdoc 2.创建容器 mkdir -p /opt/showdoc/html docker run -d --name showdoc --userroot --privilegedtrue -p 1005…...
2.14作业
1.请编程实现二维数组的杨辉三角。 2.请编程实现二维数组计算每一行的和以及列和。 3.请编程实现二维数组计算第二大值。 4.请使用非函数方法实现系统函数strcat,strcmp,strcpy,strlen. strcat: strcmp: strcpy: strlen:...
01.数据结构篇-链表
1.找出两个链表的交点 160. Intersection of Two Linked Lists (Easy) Leetcode / 力扣 例如以下示例中 A 和 B 两个链表相交于 c1: A: a1 → a2↘c1 → c2 → c3↗ B: b1 → b2 → b3 但是不会出现以下相交的情况,因为每个节点只有一个…...
揭秘产品迭代计划制定:从0到1打造完美迭代策略
产品迭代计划是产品团队确保他们能够交付满足客户需求的产品以及实现其业务目标的重要工具。开发一个成功的产品迭代计划需要仔细考虑产品的目标、客户需求、市场趋势和可用资源。以下是帮助您创建产品迭代计划的一些步骤:建立产品目标、收集客户反馈、分析市场趋势…...
Python进阶--下载想要的格言(基于格言网的Python爬虫程序)
注:由于上篇帖子(Python进阶--爬取下载人生格言(基于格言网的Python3爬虫)-CSDN博客)篇幅长度的限制,此篇帖子对上篇做一个拓展延伸。 目录 一、爬取格言网中想要内容的url 1、找到想要的内容 2、抓包分析,找到想…...
C语言--------数据在内存中的存储
1.整数在内存中的存储 整数在内存是以补码的形式存在的; 整型家族包括char,int ,long long,short类型; 因为char类型是以ASCII值形式存在,所以也是整形家族; 这四种都包括signed,unsigned两种,即有符号和无符号&am…...
【Java】零基础蓝桥杯算法学习——线性动态规划(一维dp)
线性dp——一维动态规划 1、考虑最后一步可以由哪些状态得到,推出转移方程 2、考虑当前状态与哪些参数有关系,定义几维数组来表示当前状态 3、计算时间复杂度,判断是否需要进行优化。 一维动态规划例题:最大上升子序列问题 Java参…...
Excel模板1:彩色甘特图
Excel模板1:彩色甘特图 分享地址 当前效果:只需要填写进度, 其余效果都是自动完成的 。 阿里网盘永久分享:https://www.alipan.com/s/cXhq1PNJfdm 省心。能用公式的绝不使用手动输入。 这个区域以及标题可以手动输入…...
如何重新安装 macOS
你可以使用电脑的内建恢复系统“macOS 恢复”来重新安装 Mac 操作系统。不但简单快捷,而且重新安装后不会移除你的个人数据。 将 Mac 关机 选取苹果菜单 >“关机”,然后等待 Mac 关机。如果你无法将 Mac 关机,请按住它的电源按钮最长 …...
论文阅读-Pegasus:通过网络内一致性目录容忍分布式存储中的偏斜工作负载
论文名称:Pegasus: Tolerating Skewed Workloads in Distributed Storage with In-Network Coherence Directories 摘要 高性能分布式存储系统面临着由于偏斜和动态工作负载引起的负载不平衡的挑战。本文介绍了Pegasus,这是一个利用新一代可编程交换机…...
【PTA|编程题|期末复习】字符串(一)
【C语言/期末复习】字符和字符串函数(附思维导图/例题) 目录 7-1 组织星期信息 输入样例 (repeat3) : 输出样例: 代码 7-2 查找指定字符 输入格式: 输出格式: 输入样例1: 输出样例1: 输入样例2: …...
数据库基本操作2
一.DML(Data Manipulation Language) 用来对数据库中表的数据记录进行更新 关键字:增删改 插入insert 删除delete 更新update 1.数据插入 insert into 表(列名1,列名2,列名3……)values&a…...
BTC破5W+QAQ
比特币突破5万美元 创2021年来最高 比特币在龙年伊始涨超6.8%。在大年初四(2月13日)一度最高涨至5万零383美元。 今年1月,当市场期待已久的现货比特币交易所挂牌基金(ETF)推出后,比特币遭抛售,…...
Xubuntu16.04系统中修改系统语言和系统时间
1.修改系统语言 问题:下图显示系统语言不对 查看系统中可用的所有区域设置的命令 locale -a修改/etc/default/locale文件 修改后如下: # File generated by update-locale LANG"en_US.UTF-8" LANGUAGE"en_US:en"LANG"en_US…...
内网穿透 | 推荐两个免费的内网穿透工具
目录 1、简介 2、Ngrok 2.1、下载安装 2.2、运行 2.3、固定域名 2.4、配置多服务 3、cpolar 3.1、下载安装 3.2、运行 🍃作者介绍:双非本科大三网络工程专业在读,阿里云专家博主,专注于Java领域学习,擅长web应…...
Android中代码生成图片高级部分
1、引言 上一篇文章已经介绍了使用bitmap对象生成图片,但android中不仅仅可以直接使用bitmap对象生成图片,也能借助bitmap对象将布局文件转化为图片,实际应用时,我们需要将两者结合起来,只有这样才能生成更加绚丽的图片…...
计算机网络——09Web-and-HTTP
Web and HTTP 一些术语 Web页:由一些对象组成对象可以是HTML文件、JPEG图像,JAVA小程序,声音剪辑文件等Web页含有一个基本的HTML文件,该基本HTML文件又包含若干对象的引用(链接)通过URL对每个对象进行引用…...
【教程】MySQL数据库学习笔记(一)——认识与环境搭建(持续更新)
写在前面: 如果文章对你有帮助,记得点赞关注加收藏一波,利于以后需要的时候复习,多谢支持! 【MySQL数据库学习】系列文章 第一章 《认识与环境搭建》 第二章 《数据类型》 文章目录 【MySQL数据库学习】系列文章一、认…...
软件测试-测试用例研究-如何编写一份优秀的测试用例
什么是测试用例 测试用例是一组由测试输入、执行条件、预期结果等要素组成,以完成对某个特定需求或者目标测试的数据,体现测试方案、方法、技术和策略的文档。测试用例是软件测试的核心,它把测试系统的操作步骤用文档的形式描述出来…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
第八部分:阶段项目 6:构建 React 前端应用
现在,是时候将你学到的 React 基础知识付诸实践,构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段,你可以先使用模拟数据,或者如果你的后端 API(阶段项目 5)已经搭建好,可以直接连…...
向量几何的二元性:叉乘模长与内积投影的深层联系
在数学与物理的空间世界中,向量运算构成了理解几何结构的基石。叉乘(外积)与点积(内积)作为向量代数的两大支柱,表面上呈现出截然不同的几何意义与代数形式,却在深层次上揭示了向量间相互作用的…...
