用两行代码实现重试功能,spring-retry真是简单而优雅
背景
最近做的一个需求,需要调用第三方接口。正常情况下,接口的响应是符合要求的,只有在网络抖动等极少数的情况下,会存在超时情况。因为是小概率事件,所以一次超时之后,进行一次重试操作应该就可以了。重试很简单,设定最多的重试次数,用一个循环来实现就好了。比如一次请求是这样:
@Controller
public class RetryController {
@Autowired
private RetryRequestService retryRequestService;
public String doSth(String param) {
String result = retryRequestService.request(param);
return "响应是" + result;
}
}
改成重试三次,可以是这样:
@Controller
public class RetryController {
@Autowired
private RetryRequestService retryRequestService;
public String doSth(String param) {
int count = 0;
String result = "";
while (count < 3) {
try {
result = retryRequestService.request(param);
break;
} catch (Exception e) {
count++;
}
}
return "响应是" + result;
}
}
如果请求接口超时(抛异常)了,那么会继续进入下一次循环重试。如果在超时时间内获取到了结果,那就结束循环,继续往下走。
用倒是能用,但是太丑了。不好看,还狠狠的侵入了原有的代码。所以有没有更优雅的方式呢?
快速接入spring-retry
这么常用的东西,肯定有轮子啊!于是spring-retry闪亮登场!
这是一个属于Spring全家桶的项目,也是被广泛运用的组件。在这里我默认你是个Spring Boot的项目了哈。
使用起来非常简单,只需要三步。
1、引入依赖
<!--springboot项目都不用引入版本号-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<!--还是需要aop的支持的-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
2、在启动类上加注解@EnableRetry
此举是让你的Spring Boot项目支持spring-retry的重试功能。像这样:
@SpringBootApplication
@EnableRetry
@Slf4j
public class FastKindleApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(FastKindleApplication.class, args);
String result = applicationContext.getBean(RetryController.class).doSth("");
log.info(result);
}
}
3、在需要重试的方法上加注解@Retryable
如上文所说,我们需要重试的方法是retryRequestService.request这个方法。那么我们就在这个方法上加@Retryable注解。如下:
@Service
@Slf4j
public class RetryRequestService {
@Autowired
private OtherSystemSpi otherSystemSpi;
@Retryable(value = RuntimeException.class, maxAttempts = 5, backoff = @Backoff(delay = 100))
public String request(String param) {
double random = Math.random();
log.info("请求进来了,随机值为:" + random);
if (random > 0.1) {
throw new RuntimeException("超时");
}
return otherSystemSpi.request(param);
}
}
当然,我们这里写了个调皮的逻辑来模拟超时。如果随机值大于0.1则抛出一个RuntimeException异常。每次请求进来时都会输出日志。
我来解释一下@Retryable注解中的信息。
- value = RuntimeException.class:是指方法抛出RuntimeException异常时,进行重试。这里可以指定你想要拦截的异常。
- maxAttempts:是最大重试次数。如果不写,则是默认3次。
- backoff = @Backoff(delay = 100):是指重试间隔。delay=100意味着下一次的重试,要等100毫秒之后才能执行。
我们来执行一下,可以看到日志输出:
2022-03-15 23:51:19.754 INFO 3343 --- [main] c.e.fastkindle.FastKindleApplication : Started FastKindleApplication in 0.347 seconds (JVM running for 0.536)
2022-03-15 23:51:19.762 INFO 3343 --- [main] c.e.f.service.retry.RetryRequestService : 请求进来了,随机值为:0.11030214774098712
2022-03-15 23:51:19.867 INFO 3343 --- [main] c.e.f.service.retry.RetryRequestService : 请求进来了,随机值为:0.09624689154608002
2022-03-15 23:51:19.867 INFO 3343 --- [main] c.e.fastkindle.FastKindleApplication : 响应是mock
前两次的随机值都大于0.1,所以进行了重试,而且注意时间,都是间隔了大概100毫秒输出的日志。第三次的随机值小于0.1,就直接返回数据了。
我又试了几次,使五次请求的随机值都大于0.1,则结果是进行了五次请求,最后抛出了个异常。
2022-03-15 23:52:58.193 INFO 3449 --- [main] c.e.fastkindle.FastKindleApplication : Started FastKindleApplication in 0.41 seconds (JVM running for 0.635)
2022-03-15 23:52:58.201 INFO 3449 --- [main] c.e.f.service.retry.RetryRequestService : 请求进来了,随机值为:0.5265644192525288
2022-03-15 23:52:58.303 INFO 3449 --- [main] c.e.f.service.retry.RetryRequestService : 请求进来了,随机值为:0.6343538744876432
2022-03-15 23:52:58.407 INFO 3449 --- [main] c.e.f.service.retry.RetryRequestService : 请求进来了,随机值为:0.5482463853575078
2022-03-15 23:52:58.511 INFO 3449 --- [main] c.e.f.service.retry.RetryRequestService : 请求进来了,随机值为:0.5624923285641071
2022-03-15 23:52:58.616 INFO 3449 --- [main] c.e.f.service.retry.RetryRequestService : 请求进来了,随机值为:0.305945622979098
Exception in thread "main" java.lang.RuntimeException: 超时
at com.esparks.fastkindle.service.retry.RetryRequestService.request(RetryRequestService.java:24)
at com.esparks.fastkindle.service.retry.RetryRequestService$$FastClassBySpringCGLIB$$50f0bdca.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
总结
好啦,咱今天就介绍一下快速的接入spring-retry来实现重试功能。更详细的功能和实现原理,之后再详细介绍吧(又给自己挖了个坑)
用两行代码实现重试功能,spring-retry真是简单而优雅的更多相关文章
- 异常重试框架Spring Retry实践
前期准备在Maven项目中添加Spring Retry和切面的依赖 POM: <!-- Spring Retry --> <dependency> <groupId> ...
- Spring异常重试框架Spring Retry
Spring Retry支持集成到Spring或者Spring Boot项目中,而它支持AOP的切面注入写法,所以在引入时必须引入aspectjweaver.jar包. 快速集成的代码样例: @Con ...
- Spring Retry 重试
重试的使用场景比较多,比如调用远程服务时,由于网络或者服务端响应慢导致调用超时,此时可以多重试几次.用定时任务也可以实现重试的效果,但比较麻烦,用Spring Retry的话一个注解搞定所有.话不多说 ...
- Spring Retry 在SpringBoot 中的应用
Spring Boot中使用Spring-Retry重试框架 Spring Retry提供了自动重新调用失败的操作的功能.这在错误可能是暂时的(例如瞬时网络故障)的情况下很有用. 从2.2.0版本开始 ...
- 自己动手实践 spring retry 重试框架
前序 马上过年了,预祝大家,新年快乐,少写bug 什么是spring retry? spring retry是从spring batch独立出来的一个能功能,主要实现了重试和熔断. 什么时候用? 远程 ...
- Spring框架中一个有用的小组件:Spring Retry
1.概述 Spring Retry 是Spring框架中的一个组件, 它提供了自动重新调用失败操作的能力.这在错误可能是暂时发生的(如瞬时网络故障)的情况下很有帮助. 在本文中,我们将看到使用Spri ...
- Spring retry基本使用
Spring retry基本使用 背景介绍 在实际工作过程中,重试是一个经常使用的手段.比如MQ发送消息失败,会采取重试手段,比如工程中使用RPC请求外部服务,可能因为网络 波动出现超时而采取重试手段 ...
- spring retry 使用
1. 场景 系统方法调用时无状态的,同时因为网络原因,或者系统暂时故障,进行的重试 2. maven 依赖 <project xmlns="http://maven.apa ...
- Spring Retry
最近组内准备将项目中原有的重试功能抽取出来重构为一个重试平台,由于对重试的功能要求比较高,采用了不少中间件和框架(jimdb,jproxy, Elastic-Job ,JMQ,Hbase, Disru ...
随机推荐
- PTM人员(产品技术经理)
以下是一位PTM的工作总结: 责任感 作为PTM一定要有责任感,项目中的所有事情都要作为自己的事情,如果碰到有些项目中的工作没人负责,那么就是PTM的工作没有做到位. 全局观 作为PTM一定要比普 ...
- 4.Flink实时项目之数据拆分
1. 摘要 我们前面采集的日志数据已经保存到 Kafka 中,作为日志数据的 ODS 层,从 kafka 的ODS 层读取的日志数据分为 3 类, 页面日志.启动日志和曝光日志.这三类数据虽然都是用户 ...
- 4、网络并发编程--僵尸进程、孤儿进程、守护进程、互斥锁、消息队列、IPC机制、生产者消费者模型、线程理论与实操
昨日内容回顾 操作系统发展史 1.穿孔卡片 CPU利用率极低 2.联机批处理系统 CPU效率有所提升 3.脱机批处理系统 CPU效率极大提升(现代计算机雏形) 多道技术(单核CPU) 串行:多个任务依 ...
- 拒绝for循环,从take_along_axis开始
技术背景 在前一篇文章中,我们提到了关于Numpy中的各种取index的方法,可以用于取出数组里面的元素,也可以用于做切片,甚至可以用来做排序.但是遇到对于高维矩阵的某一个维度取多个值的时候,单纯的使 ...
- 数据库delete from和truncate删除的区别详解
一:区别 1.delete from 后面可以直接接条件,truncate不可以 2.delete from 记录是一条条删除的,所删除的每行记录都会进入日志,而truncate一次性删除整个页,因此 ...
- 攻防世界Web_easytornado
题目: 解题思路: 题目就三个txt文本文件 , 由python_template_injection这篇随笔中了解到tornado也是python web应用程序模板的一种,应该也是考查模板注入. ...
- PhpStudy集成环境安装教程
地址:https://www.xp.cn/ 下载软件,直接安装即可.注意路径不能带有空格.安装完成,启动后如下图: 1.数据库的小白操作:先启动服务器Apache和数据库MySQL,如箭头所示 2.可 ...
- proto编译组件使用
proto编译组件使用 前提:所有组件已经安装好,包括: protoc protoc-gen-go protoc-gen-grpc-gateway protoc-gen-swagger 怎么装再开一篇 ...
- 零售BI:为什么说零售行业非上一套企业BI系统不可?
如果你要问为什么现在越来越多的零售企业都会在公司上一套企业BI系统,这边文章就能解答你的疑惑. 2016年10月,马云在云栖大会上提出了"新零售"概念.在新零售时代,数字化转型打通 ...
- 如何搭建老板想要的dashborad管理驾驶舱,这篇文章值得一看!
随着企业管理向精细化发展和信息化步伐的加快,企业采集到的市场客户及内部管理数据越来越多.越来越趋向于实时,系统大量的信息给企业带来了一个问题:管理者怎么用这些数据才能掌握企业动态,做出及时关键的决策? ...