• Spring Retry


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

  • 相关阅读:
    centos PIL 安装
    apache virtualhost 针对ip开放访问
    基础练习 矩形面积交 (分类讨论)
    UVa 10163 Storage Keepers (二分 + DP)
    UVaLive 5009 Error Curves (三分)
    UVa 11542 Square (高斯消元)
    UVa 10828 Back to Kernighan-Ritchie (数学期望 + 高斯消元)
    基础练习 回形取数 (循环 + Java 输入输出外挂)
    UVaLive 3704 Cellular Automaton (循环矩阵 + 矩阵快速幂)
    勇敢的妞妞 (状压 + 搜索)
  • 原文地址:https://www.cnblogs.com/jtlgb/p/6813164.html
Copyright © 2020-2023  润新知