当前位置: 首页 > news >正文

在Spring Boot中使用Spring Retry

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

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

转载于:https://my.oschina.net/wangxincj/blog/827221

相关文章:

  • 用C#开发Windows服务监控系统使用
  • 8VC Venture Cup 2017 - Elimination Round - A
  • PostgreSQL SystemTap on Linux
  • Java 操作XML,JDOMDOM4J
  • React怎么创建.babelrc文件
  • JavaSE 学习参考:switch语句
  • Git使用技巧(1)-- 配置【持续更新】
  • Maven 上传 jar 到 私服命令
  • 我们发的不是红包,而关系证明
  • grep和sed匹配多个字符关键字的用法
  • mybatis的延迟加载
  • OVS VxLAN Flow 分析 - 每天5分钟玩转 OpenStack(149)
  • [Manacher]【学习笔记】
  • python 常见问题总结
  • http通信json解析过滤无关字符
  • AHK 中 = 和 == 等比较运算符的用法
  • codis proxy处理流程
  • input实现文字超出省略号功能
  • JAVA_NIO系列——Channel和Buffer详解
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • Python语法速览与机器学习开发环境搭建
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • webpack4 一点通
  • 巧用 TypeScript (一)
  • 入口文件开始,分析Vue源码实现
  • 详解移动APP与web APP的区别
  • 用Canvas画一棵二叉树
  • ​如何在iOS手机上查看应用日志
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • (2)STL算法之元素计数
  • (2.2w字)前端单元测试之Jest详解篇
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (WSI分类)WSI分类文献小综述 2024
  • (zz)子曾经曰过:先有司,赦小过,举贤才
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .vue文件怎么使用_vue调试工具vue-devtools的安装
  • @JSONField或@JsonProperty注解使用
  • @Service注解让spring找到你的Service bean
  • [ CTF ]【天格】战队WriteUp- 2022年第三届“网鼎杯”网络安全大赛(青龙组)
  • [ vulhub漏洞复现篇 ] Apache APISIX 默认密钥漏洞 CVE-2020-13945
  • [ vulhub漏洞复现篇 ] ECShop 2.x / 3.x SQL注入/远程执行代码漏洞 xianzhi-2017-02-82239600
  • [ 渗透工具篇 ] 一篇文章让你掌握神奇的shuize -- 信息收集自动化工具
  • [1159]adb判断手机屏幕状态并点亮屏幕
  • [Android]使用Git将项目提交到GitHub
  • [ARM]ldr 和 adr 伪指令的区别
  • [BSGS算法]纯水斐波那契数列
  • [C语言]一维数组二维数组的大小
  • [Firefly-Linux] RK3568修改控制台DEBUG为普通串口UART
  • [Google Guava] 1.1-使用和避免null
  • [GXYCTF2019]BabySQli1
  • [JDBC-1] JDBC Base Template
  • [Linux] Boot分区满了的处理方法 The volume boot has only 0 bytes disk space remaining