最近组内准备将项目中原有的重试功能抽取出来重构为一个重试平台,由于对重试的功能要求比较高,采用了不少中间件和框架(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. mysql 按照 where in 排序

    select * from user_extend where `unique` in('mark.liu@xxxx.com','jason.gan@xxxx.com','ssgao@xxxx.com ...

  2. Linux内核深入研究之进程的线性地址空间-传统版

    引言: 了解Linux环境下,进程的地址空间划分,对于我们理解Linux应用程序有很大的帮助,否则会被New与Malloc之类的指针操作弄的晕头转向,本文基于Linux内核讲述了Linux/Unix线 ...

  3. 【Spring学习笔记-MVC-3】SpringMVC返回Json数据-方式1

    <Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...

  4. RabbitMQ-2 工作队列

    参考:http://rabbitmq.mr-ping.com/ 工作队列 (使用pika 0.9.5 Python客户端) 在第一篇教程中,我们已经写了一个从已知队列中发送和获取消息的程序.在这篇教程 ...

  5. puppet 工作原理

    Puppet的工作细节分成如下几个步骤: 1.客户端puppetd调用facter,facter会探测出这台主机的一些变量如主机名.内存大小.IP地址等.然后puppetd把这些信息发送到服务器端. ...

  6. python selenium-7自动发送邮件

    https://jingyan.baidu.com/article/647f0115b78f8d7f2148a8e8.html 1.发送HTML格式的邮件 import smtplib from em ...

  7. MYSQL ERROR 1045 (28000): Access denied for user (using password: YES)解决方案详细说明

    1.首先这个问题出现的原因不详,可能是mysql的bug吧   2 解决步骤      1.首先停下mysql的服务  作者系统下命令为   /etc/init.d/mysqld stop  具体的停 ...

  8. Centos7安装docker(转!)

    时间在自己的运动中也会碰到挫折,遇到障碍,所以某一段时间也会滞留在哪一个房间里 <百年孤独> 转自:https://www.cnblogs.com/yufeng218/p/8370670. ...

  9. VMware中,该如何理解桥接网络与NAT 网络模式

    原创 2016年11月16日 23:26:34,原文地址如下: http://blog.csdn.net/u010801439/article/details/53193113 首先,我在VMware ...

  10. Petapoco 查询 语法

    查询语句 Sql sql = Sql.Builder; sql.Select("spb_MailAddress.*") .From("spb_MailAddress&qu ...