使用Spring RetryTemplate优雅的进行重试

2020-03-24 16:21:11来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

使用Spring RetryTemplate优雅的进行重试

1、使用场景

  • 在我们与下游通过http进行数据交互时,会约定接口协议,比如:双方约定返回20000时,可以重新请求获取正确的结果。
  • 在进行http进行网络通信时,经常会发生一些网络层面的异常如:IOException:unexpected end of stream on Connection;SocketException:Broken pipe (Write failed)、Connection reset等,比较懒的做法是加上重试逻辑,如果你是技术宅,可以深究里面的深层原因。
  • 其它任何可以重试的场景

2、常规的重试写法

    int retryTimes = 3;
    for (int i = 0; i < retryTimes; i++) {
        Result result = doSomethingPre();
        if (result == 预期值){
            doSomething();
            berak;
        }
    }

有没有觉得这段代码就像一坨shit,如果这种重试需求很多,那么打开项目就会有满屏shit。做为一个有追求的码农,不能容忍这种事情发生,接下来Spring RetryTemplate闪亮登场。

3、Spring RetryTemplate的使用

  • 引入依赖
<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>1.2.4.RELEASE</version>
</dependency>
  • 配置
    既要重试,我们肯定要定义好重试的策略:重试的触发条件,重试次数,时间间隔等要素。

RetryPolicy


下图是RetryPolicy及实现类的关系图,太大了,看不清,没关系,我们只看最简单最常用的SimpleRetryPolicy,它里面可以设置重试次数:setMaxAttempts();不设置的话,默认值是3次。

BackOffPolicy

顾名思义BackOffPolicy是退避策略,看一下他的实现类。

用ExponentialBackOffPolicy来举例子,它是指数退避策略,需设置参数
initialInterval:初始休眠时间,默认100毫秒
multiplier:指定乘数,当前休眠时间*multiplier即为下一次的休眠时间;
maxInterval:指定最大休眠时间,默认30秒,避免multiplier过大引起无限期等待。

RetryTemplate

spring容器中注入RetryTemplate这个bean,并在该bean中设置上述两个策略:

    @Bean
    public RetryTemplate simpleRetryTemplate() {
        RetryTemplate retryTemplate = new RetryTemplate();
        retryTemplate.setRetryPolicy(new SimpleRetryPolicy());
        ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
        backOffPolicy.setInitialInterval(3000);
        backOffPolicy.setMultiplier(2);
        backOffPolicy.setMaxInterval(15000);
        retryTemplate.setBackOffPolicy(backOffPolicy);
        return retryTemplate;
    }

上面的配置通俗的说就是,最大重试三次,时间间隔为3,32,32*2,且时间间隔不大于15s。

  • 使用
    retryTemplate.execute(RetryCallback<T, E> retryCallback);
    RetryCallback接口只有一个接口,即为函数式接口,可以使用lamda表达式来写,简洁且直观。
    最终写法:retryTemplate.execute(retryContext -> {重试逻辑代码});
    这段为源代码,可以省略,可以看到最终调用为RetryCallback接口的实现类,及lamda表达式
    @Override
    public final <T, E extends Throwable> T execute(RetryCallback<T, E> retryCallback) throws E {
	return doExecute(retryCallback, null, null);
    }

    protected <T, E extends Throwable> T doExecute(RetryCallback<T, E> retryCallback,RecoveryCallback<T> recoveryCallback, RetryState state)throws E, ExhaustedRetryException {
        ......
        return retryCallback.doWithRetry(context);
    }

上述是retryTemplate最简单的用法,它还有很多很强大的用法,有时间再来补充。


原文链接:https://www.cnblogs.com/sunxinxin/p/12559187.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:【JAVA进阶架构师指南】之三:深入了解类加载机制

下一篇:java jar包