最近组内准备将项目中原有的重试功能抽取出来重构为一个重试平台,由于对重试的功能要求比较高,采用了不少中间件和框架(jimdb,jproxy, Elastic-Job ,JMQ,Hbase, Disruptor ),而且重写了  BlockingQueue,平台构架也比较复杂,在设计重试平台前,也调研过一些重试的开源框架,Spring Retry映入了眼帘,虽然最后没有采用它,但是还是想在此处介绍一下它。

在分布式系统中,为了保证数据分布式事务的强一致性,大家在调用RPC接口或者发送MQ时,针对可能会出现网络抖动请求超时情况采取一下重试操作。大家用的最多的重试方式就是MQ了,但是如果你的项目中没有引入MQ,那就不方便了,本文主要介绍一下如何使用Spring Retry实现重试操作。

1、引入Spring Retry依赖

<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>

2、在启动入口加入重试配置

添加@EnableRetry注解

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

3、编写测试service

@Service
public class RetryService {
@Retryable(value= {RemoteAccessException.class},maxAttempts = 5,backoff = @Backoff(delay = 5000l,multiplier = 1))
public void retryTest() throws Exception {
System.out.println("do something...");
throw new RemoteAccessException("RemoteAccessException....");
}
@Recover
public void recover(RemoteAccessException e) {
System.out.println(e.getMessage());
System.out.println("recover....");
}
}

4、测试service

@Configuration
@EnableRetry
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class RetryServiceMain {
@Bean
public RetryService retryService(){
return new RetryService();
}
public static void main(String[] args) throws Exception{
final AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(RetryServiceMain.class);
final RetryService retryService = applicationContext.getBean(RetryService.class);
retryService.retryTest();
}
}

Run这个main方法,控制台会打印如下内容

16:12:28.932 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'retryService'
16:12:28.954 [main] DEBUG org.springframework.retry.support.RetryTemplate - Retry: count=0
do something...
16:12:28.973 [main] DEBUG org.springframework.retry.backoff.ExponentialBackOffPolicy - Sleeping for 5000
16:12:33.974 [main] DEBUG org.springframework.retry.support.RetryTemplate - Checking for rethrow: count=1
16:12:33.974 [main] DEBUG org.springframework.retry.support.RetryTemplate - Retry: count=1
do something...
16:12:33.974 [main] DEBUG org.springframework.retry.backoff.ExponentialBackOffPolicy - Sleeping for 5000
16:12:38.974 [main] DEBUG org.springframework.retry.support.RetryTemplate - Checking for rethrow: count=2
16:12:38.974 [main] DEBUG org.springframework.retry.support.RetryTemplate - Retry: count=2
do something...
16:12:38.974 [main] DEBUG org.springframework.retry.backoff.ExponentialBackOffPolicy - Sleeping for 5000
16:12:43.975 [main] DEBUG org.springframework.retry.support.RetryTemplate - Checking for rethrow: count=3
16:12:43.975 [main] DEBUG org.springframework.retry.support.RetryTemplate - Retry: count=3
do something...
16:12:43.975 [main] DEBUG org.springframework.retry.backoff.ExponentialBackOffPolicy - Sleeping for 5000
16:12:48.975 [main] DEBUG org.springframework.retry.support.RetryTemplate - Checking for rethrow: count=4
16:12:48.975 [main] DEBUG org.springframework.retry.support.RetryTemplate - Retry: count=4
do something...
16:12:48.975 [main] DEBUG org.springframework.retry.support.RetryTemplate - Checking for rethrow: count=5
16:12:48.975 [main] DEBUG org.springframework.retry.support.RetryTemplate - Retry failed last attempt: count=5
RemoteAccessException....
recover....

可见方法重试了五次,每次间隔了5秒,第五次失败后执行了recover方法。

介绍一下几个注解

  • @EnableRetry能否重试。当proxyTargetClass属性为true时,使用CGLIB代理。默认使用标准JAVA注解。在spring Boot中此参数写在程序入口即可。
  • @Retryable 标注此注解的方法在发生异常时会进行重试

value:指定处理的异常类

include:指定处理的异常类和value一样,默认为空,当exclude也为空时,默认所有异常

exclude:指定异常不处理,默认空,当include也为空时,默认所有异常

maxAttempts:最大重试次数。默认3次

backoff: 重试等待策略。默认使用@Backoff注解

  • @Backoff 重试等待策略

不设置参数时,默认使用FixedBackOffPolicy(指定等待时间),重试等待1000ms

设置delay,使用FixedBackOffPolicy(指定等待时间),重试等待填写的时间

设置delay和maxDealy时,重试等待在这两个值之间均态分布

设置delay、maxDealy、multiplier,使用 ExponentialBackOffPolicy(指数级重试间隔的实现 ),multiplier即指定延迟倍数,比如delay=5000l,multiplier=2,则第一次重试为5秒,第二次为10秒,第三次为20秒……

  • @Recover 用于@Retryable重试失败后处理方法,此注解注释的方法参数一定要是@Retryable抛出的异常,否则无法识别,可以在该方法中进行日志处理。

spring-retry项目地址:https://github.com/spring-projects/spring-retry

Spring Retry的更多相关文章

  1. Spring retry基本使用

    Spring retry基本使用 背景介绍 在实际工作过程中,重试是一个经常使用的手段.比如MQ发送消息失败,会采取重试手段,比如工程中使用RPC请求外部服务,可能因为网络 波动出现超时而采取重试手段 ...

  2. 自己动手实践 spring retry 重试框架

    前序 马上过年了,预祝大家,新年快乐,少写bug 什么是spring retry? spring retry是从spring batch独立出来的一个能功能,主要实现了重试和熔断. 什么时候用? 远程 ...

  3. Spring retry实践

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

  4. Spring异常重试框架Spring Retry

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

  5. 【spring】spring retry介绍

    一.为什么需要重试? 我们知道只要是网络请求都有失败的情况,这个时候增加retry机制是必要的.而spring全家桶中就有这么一套机制. 二.spring retry spring系列的spring ...

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

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

  7. Spring框架中一个有用的小组件:Spring Retry

    1.概述 Spring Retry 是Spring框架中的一个组件, 它提供了自动重新调用失败操作的能力.这在错误可能是暂时发生的(如瞬时网络故障)的情况下很有帮助. 在本文中,我们将看到使用Spri ...

  8. Spring Retry 在SpringBoot 中的应用

    Spring Boot中使用Spring-Retry重试框架 Spring Retry提供了自动重新调用失败的操作的功能.这在错误可能是暂时的(例如瞬时网络故障)的情况下很有用. 从2.2.0版本开始 ...

  9. Spring Retry 重试

    重试的使用场景比较多,比如调用远程服务时,由于网络或者服务端响应慢导致调用超时,此时可以多重试几次.用定时任务也可以实现重试的效果,但比较麻烦,用Spring Retry的话一个注解搞定所有.话不多说 ...

随机推荐

  1. JAVA Date类与Calendar类【转】

    Date类 在JDK1.0中,Date类是唯一的一个代表时间的类,但是由于Date类不便于实现国际化,所以从JDK1.1版本开始,推荐使用Calendar类进行时间和日期处理.这里简单介绍一下Date ...

  2. Android之WebViewClient与WebChromeClient的区别

    Android之WebViewClient与WebChromeClient的区别 2012-05-05      0个评论       收藏    我要投稿 ANDROID应用开发的时候可能会用到WE ...

  3. selenium Java-1 配置

      1.使用intellij新建一个maven项目,名字自定.在pom中写入selenium的依赖.其他依赖也添加到该文件中. [maven selenium依赖](http://mvnreposit ...

  4. 3-4 1449 web view

    1.app类型 不同类型的应用 区别 native app 纯原声app,Android用Java些,iOS用object c写 hybrid app 套用原声应用的外壳,既有原生的UI页面,又通过内 ...

  5. 部署DNS从服务器

    修改主服务器中区域信息文件: # vi /etc/named.rfc1912.zones 检查配置文件是否有错误 # named-checkconf 重启named服务程序,让配置文件生效 #syst ...

  6. 浅析Spring框架之一(Spring简介)

    免责声明 本文为鄙人搜集网络资源并结合自己所思所得整理而成,如有侵权,敬请谅解. 何为spring框架 Spring是一个开源的轻量级控制反转(IoC)和面向切面(AOP)的容器框架. ◆目的:解决企 ...

  7. 【BZOJ】1975 [Sdoi2010]魔法猪学院(A*)

    题目 传送门:QWQ 分析 k短路,Astar.估价函数是终点向外跑的最短路. 显然不是正解qwq. 代码 // By noble_ // Astar algorithm // #include &l ...

  8. InterlliJ IDEA 2017.3.x / 2017.3.4 License Server激活

    InterlliJ IDEA 2017.3.x / 2017.3.4 License Server激活 1.Lincense Server激活 // 激活IDEA的License Server 地址 ...

  9. JavaScript中的数组和字符串

    知识内容: 1.JavaScript中的数组 2.JavaScript中的字符串 一.JavaScript中的数组 1.JavaScript中的数组是什么 数组指的是数据的有序列表,每种语言基本上都有 ...

  10. OpenACC 简单的原子操作

    ▶ OpenACC 的原子操作,用到了 C++ 的一个高精度计时器 ● 代码,直接的原子操作 #include <iostream> #include <cstdlib> #i ...