@Retryable

前言

在实际工作中,重处理是一个非常常见的场景,比如:

  • 发送消息失败。
  • 调用远程服务失败。
  • 争抢锁失败。

这些错误可能是因为网络波动造成的,等待过后重处理就能成功。通常来说,会用try/catchwhile循环之类的语法来进行重处理,但是这样的做法缺乏统一性,并且不是很方便,要多写很多代码。然而spring-retry却可以通过注解,在不入侵原有业务逻辑代码的方式下,优雅的实现重处理功能。

一、@Retryable是什么?

spring系列的spring-retry是另一个实用程序模块,可以帮助我们以标准方式处理任何特定操作的重试。在spring-retry中,所有配置都是基于简单注释的。

二、使用步骤

1.POM依赖

  <!-- 因为是基于AOP实现的 所以引入AOP依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>

2.启用@Retryable

@EnableRetry
@SpringBootApplication
public class TestApplication { public static void main(String[] args) {
SpringApplication.run(TestApplication .class, args);
}
}

3.在方法上添加@Retryable

@Service
public class TestRetryServiceImpl implements TestRetryService { @Override
@Retryable(value = Exception.class,maxAttempts = 10,backoff = @Backoff(delay = 2000,multiplier = 1.5))
public int testRetry(int code, String userName, List<String> list) throws Exception{
System.out.println("testRetry被调用,时间:"+LocalTime.now());
if (code==0){
throw new Exception("发生错误!!!");
}
System.out.println("testRetry被调用,成功!!!"); return 200;
}
}

来简单解释一下注解中几个参数的含义:

  • value:抛出指定异常才会重试
  • include:和value一样,默认为空,当exclude也为空时,默认所有异常
  • exclude:指定不处理的异常
  • maxAttempts:最大重试次数,默认3次
  • backoff:重试等待策略,默认使用@Backoff@Backoff的value默认为1000L,我们设置为2000L;multiplier(指定延迟倍数)默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为1.5,则第一次重试为2秒,第二次为3秒,第三次为4.5秒。

当重试耗尽时还是失败,会出现什么情况呢?

当重试耗尽时,RetryOperations可以将控制传递给另一个回调,即Spring-Retry还提供了@Recover注解,用于@Retryable`重试失败后处理方法。如果不需要回调方法,可以直接不写回调方法,那么实现的效果是,重试次数完了后,如果还是没成功没符合业务判断,就抛出异常。

4.@Recover

@Recover
public int recover(Exception e, int code, String userName, List<String> list){
System.out.println("回调方法执行!!!!");
//参数的顺序要和上方方法的顺序一致,否则会出现参数类型不匹配
System.out.println(code);
System.out.println(userName);
System.out.println(list);
//记日志到数据库 或者调用其余的方法
return 400;
}

可以看到传参里面写的是 Exception e,这个是作为回调的接头暗号(重试次数用完了,还是失败,我们抛出这个Exception e通知触发这个回调方法)。对于@Recover注解的方法,需要特别注意的是:

  • 方法的返回值必须与@Retryable方法一致
  • 方法的第一个参数,必须是Throwable类型的,建议是与@Retryable配置的异常一致,其他的参数,需要哪个参数,写进去就可以了(@Recover方法中有的)
  • 该回调方法与重试方法写在同一个实现类里面

5. 注意事项

  • 由于是基于AOP实现,所以不支持类里自调用方法
  • 如果重试失败需要给@Recover注解的方法做后续处理,那这个重试的方法不能有返回值,只能是void
  • 方法内不能使用try catch,只能往外抛异常
  • @Recover注解来开启重试失败后调用的方法(注意,需跟重处理方法在同一个类中),此注解注释的方法参数一定要是@Retryable抛出的异常,否则无法识别,可以在该方法中进行日志处理。

@Retryable注解的使用的更多相关文章

  1. 扒一扒@Retryable注解,很优雅,有点意思!

    你好呀,我是歪歪. 前几天我 Review 代码的时候发现项目里面有一坨逻辑写的非常的不好,一眼望去简直就是丑陋之极. 我都不知道为什么会有这样的代码存在项目里面,于是我看了一眼提交记录准备叫对应的同 ...

  2. 关于Spring注解@Async引发其他注解失效

    概述 在前面一篇文章中,介绍,在一个Bean中注入自己,如果有@Async和@Transaction,如果使用@Autowire注入自身,会报循环依赖,如果使用BeanFactoryAware注入自己 ...

  3. 用spring-retry注解自动触发重试方法

    原文地址:https://www.jianshu.com/p/ee02d6125113 需求背景: 有些时候我们再调用一些第三方服务的时候,从第三方那边拉数据. 但是第三方服务不是100%稳定的,有些 ...

  4. 一个注解@Recover搞定丑陋的循环重试代码

    使用背景 在实际项目中其中一部分逻辑可能会因为调用了外部服务或者等待锁等情况下出现不可预料的异常,在这个时候我们可能需要对调用这部分逻辑进行重试,代码里面主要就是使用for循环写一大坨重试的逻辑,各种 ...

  5. Spring异步调用原理及SpringAop拦截器链原理

    一.Spring异步调用底层原理 开启异步调用只需一个注解@EnableAsync @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTI ...

  6. springboot retry

    try/catch,while 循环或者定时任务  这样看起来 好  low sping boot  retry , 这样代码更简洁 eg: @Retryable(value= {RemoteAcce ...

  7. Spring retry实践

    在开发中,重试是一个经常使用的手段.比如MQ发送消息失败,会采取重试手段,比如工程中使用RPC请求外部服务,可能因为网络波动出现超时而采取重试手段......可以看见重试操作是非常常见的一种处理问题, ...

  8. Spring异常重试框架Spring Retry

    Spring Retry支持集成到Spring或者Spring Boot项目中,而它支持AOP的切面注入写法,所以在引入时必须引入aspectjweaver.jar包. 快速集成的代码样例: @Con ...

  9. 异常重试框架Spring Retry实践

    前期准备在Maven项目中添加Spring Retry和切面的依赖 POM: <!-- Spring Retry --> <dependency> <groupId> ...

  10. springboot 整合retry(重试机制)

    当我们调用一个接口可能由于网络等原因造成第一次失败,再去尝试就成功了,这就是重试机制,spring支持重试机制,并且在Spring Cloud中可以与Hystaix结合使用,可以避免访问到已经不正常的 ...

随机推荐

  1. CDH6.2.0 搭建大数据集群

    1. 资料准备 现在官网https://www.cloudera.com 需要注册账号,未来可能会收费等问题,十分麻烦,这里有一份我自己百度云的备份 链接: https://pan.baidu.com ...

  2. [报错]-RuntimeError: Input type (torch.cuda.HalfTensor) and weight type (torch.cuda.FloatTensor) should be the same

    RuntimeError: Input type (torch.cuda.HalfTensor) and weight type (torch.cuda.FloatTensor) should be ...

  3. k8s驱逐篇(4)-kube-scheduler抢占调度驱逐

    介绍kube-scheduler抢占调度驱逐之前,先简单的介绍下kube-scheduler组件: kube-scheduler简介 kube-scheduler组件是kubernetes中的核心组件 ...

  4. 升级Windows 2003域控制器到Windows 2012 R2

    由于Windows 2003包括R2的扩展支持在今年7月14日就会过期.如果在扩展周期结束之前没有和微软签订昂贵服务协议,那么系统将得不到任何补丁和技术支持. 我这里准备了两台测试用的机器做这个实验. ...

  5. Python数据分析教程(一):Numpy

    原文链接:https://blog.onefly.top/posts/13140.html 数据的纬度 一维数据:列表和集合类型 二维数据:列表类型 多维数据:列表类型 高维数据:字典类型或数据表示格 ...

  6. Kibana可视化数据(Visualize)

    在侧边导航栏点击 Visualize 开始视化您的数据. Visualize 工具能让您通过多种方式浏览您的数据.例如:我们使用饼图这个重要的可视化控件来查看银行账户样本数据中的账户余额.点击屏幕中间 ...

  7. linux开机自启服务

    前言:最近,有一个项目需要用到开机自动启动机房,所以就研究了一下 1.把node的快捷方式放在放在/usr/bin/(环境变量)下面,所有的命令默认是从这里面进行调用的 ln -s /home/too ...

  8. PAT (Basic Level) Practice 1033 旧键盘打字 分数 20

    旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现.现在给出应该输入的一段文字.以及坏掉的那些键,打出的结果文字会是怎样? 输入格式: 输入在 2 行中分别给出坏掉的那些键.以及应该输入 ...

  9. Python 实现Tracert追踪TTL值

    Tracert 命令跟踪路由原理是IP路由每经过一个路由节点TTL值会减一,假设TTL值=0时数据包还没有到达目标主机,那么该路由则会回复给目标主机一个数据包不可达,由此我们就可以获取到目标主机的IP ...

  10. 洛谷P2627 [USACO11OPEN]Mowing the Lawn G (单调队列优化DP)

    一道单调队列优化DP的入门题. f[i]表示到第i头牛时获得的最大效率. 状态转移方程:f[i]=max(f[j-1]-sum[j])+sum[i] ,i-k<=j<=i.j的意义表示断点 ...