美文网首页
guava-retrying 重试组件

guava-retrying 重试组件

作者: timothyue1 | 来源:发表于2021-01-20 16:14 被阅读0次

    一、定义

    重试机制可以保护系统减少因网络波动、依赖服务短暂性不可用带来的影响,让系统能更稳定的运行的一种保护机制。

    二、实现

    因为guava-retrying是基于Google的核心类库guava的重试机制实现,所以需要依赖guava的包,这里记得引入下。例子如下:

    Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
            .retryIfException()
            .retryIfResult(aBoolean -> Objects.equals(aBoolean, false))
            .withAttemptTimeLimiter(AttemptTimeLimiters.fixedTimeLimit(10, TimeUnit.SECONDS, Executors.newCachedThreadPool()))
            .withWaitStrategy(WaitStrategies.fixedWait(5, TimeUnit.SECONDS))
            .withStopStrategy(StopStrategies.stopAfterAttempt(5))
            .withRetryListener(new RetryListener() {
                @Override
                public <V> void onRetry(Attempt<V> attempt) {
                    System.out.print("retry time=" + attempt.getAttemptNumber());
                }
            }).build();
    try {
        retryer.call(() -> {
            // 逻辑处理
            return null;
        });
    } catch (Exception e) {
        System.out.println("exception:" + e);
    }
    
    

    这就是一个重试机制的实现了,比较简单,我们来看下具体接口及相应的策咯。

    • newBuilder:创建RetryerBuilder对象,通过该类进行构建各种重试策咯;
    • retryIfException:抛出异常时重试,但抛出error不会重试;另外该方法还包含一个重载的方法,可以自定义针对异常的实现;
    • retryIfRuntimeException:见名知义,抛出RuntimeException时重试;
    • retryIfExceptionOfType:抛出指定异常类型时重试;
    • retryIfResult:根据具体的返回值选择重试;
    • withRetryListener:在重试的时候进行事件监听,这中间我们可以记录下错误日志什么的;可以注册多个事件监听器,会按照注册顺序依次调用;
    • withWaitStrategy:重试等待策略,核心策咯之一;
    • withStopStrategy:重试停止策略,核心策咯之一;
    • withBlockStrategy:重试阻塞策略,也就是两次重试的时间间隔的实现方式;
    • withAttemptTimeLimiter:单次任务执行时长限制(如果单次任务执行超时,则终止执行当前任务);
    • build:通过newBuilder构建了各种重试策咯,构建完成,还需要通过build方法借助Retryer来执行;

    接下来,我们来看一下主要的几个策咯及核心类。

    1. WaitStrategies 重试等待策略
    1.1 ExponentialWaitStrategy 指数等待策略

    指数补偿 算法 Exponential Backoff

    .withWaitStrategy(WaitStrategies.exponentialWait(100, 5, TimeUnit.MINUTES))
    
    

    创建一个永久重试的重试器,每次重试失败时以递增的指数时间等待,直到最多5分钟。 5分钟后,每隔5分钟重试一次。对该例而言:

    第一次失败后,依次等待时长:2^1 * 100;2^2 * 100;2^3 * 100;...
    
    

    在ExponentialWaitStrategy中,根据重试次数计算等待时长的源码我们可以关注下:

    @Override
    public long computeSleepTime(Attempt failedAttempt) {
        double exp = Math.pow(2, failedAttempt.getAttemptNumber());
        long result = Math.round(multiplier * exp);
        if (result > maximumWait) {
            result = maximumWait;
        }
        return result >= 0L ? result : 0L;
    }
    
    

    如果以后有类似的需求,我们可以自己写下这些算法,而有关更多指数补偿 算法 Exponential Backoff,可以参考:http://en.wikipedia.org/wiki/Exponential_backoff


    1.2 FibonacciWaitStrategy 斐波那契等待策略

    Fibonacci Backoff 斐波那契补偿算法

    .withWaitStrategy(WaitStrategies.fibonacciWait(100, 2, TimeUnit.MINUTES))
    
    

    创建一个永久重试的重试器,每次重试失败时以斐波那契数列来计算等待时间,直到最多2分钟;2分钟后,每隔2分钟重试一次;对该例而言:

    第一次失败后,依次等待时长:1*100;1*100;2*100;3*100;5*100;...
    
    

    1.3 FixedWaitStrategy 固定时长等待策略
    withWaitStrategy(WaitStrategies.fixedWait(10,  TimeUnit.SECONDS))
    
    

    固定时长等待策略,失败后,将等待固定的时长进行重试;


    1.4 RandomWaitStrategy 随机时长等待策略
    withWaitStrategy(WaitStrategies.randomWait(10,  TimeUnit.SECONDS));
    withWaitStrategy(WaitStrategies.randomWait(1,  TimeUnit.SECONDS, 10, TimeUnit.SECONDS));
    
    

    随机时长等待策略,可以设置一个随机等待的最大时长,也可以设置一个随机等待的时长区间。


    1.5 IncrementingWaitStrategy 递增等待策略
    withWaitStrategy(WaitStrategies.incrementingWait(1,  TimeUnit.SECONDS, 5, TimeUnit.SECONDS))
    
    

    递增等待策略,根据初始值和递增值,等待时长依次递增。就本例而言:

    第一次失败后,将依次等待1s;6s(1+5);11(1+5+5)s;16(1+5+5+5)s;...


    1.6 ExceptionWaitStrategy 异常等待策略
    withWaitStrategy(WaitStrategies.exceptionWait(ArithmeticException.class, e -> 1000L))
    
    

    根据所发生的异常指定重试的等待时长;如果异常不匹配,则等待时长为0;


    1.7 CompositeWaitStrategy 复合等待策略
    .withWaitStrategy(WaitStrategies.join(WaitStrategies.exceptionWait(ArithmeticException.class, e -> 1000L),WaitStrategies.fixedWait(5, TimeUnit.SECONDS)))
    
    

    复合等待策略;如果所执行的程序满足一个或多个等待策略,那么等待时间为所有等待策略时间的总和。

    2. StopStrategies 重试停止策略
    2.1 NeverStopStrategy
    withStopStrategy(StopStrategies.neverStop())
    
    

    一直不停止,一直需要重试。


    2.2 StopAfterAttemptStrategy
    withStopStrategy(StopStrategies.stopAfterAttempt(3))
    
    

    在重试次数达到最大次数之后,终止任务。


    2.3 StopAfterDelayStrategy
    withStopStrategy(StopStrategies.stopAfterDelay(3, TimeUnit.MINUTES))
    
    

    在重试任务达到设置的最长时长之后,无论任务执行次数,都终止任务。

    3. BlockStrategies 阻塞策略

    阻塞策略默认提供的只有一种:ThreadSleepStrategy,实现方式是通过Thread.sleep(sleepTime)来实现;不过这也给了我们极大的发挥空间,我们可以自己实现阻塞策略。

    4. AttemptTimeLimiters 任务执行时长限制

    这个表示单次任务执行时间限制(如果单次任务执行超时,则终止执行当前任务);

    4.1 NoAttemptTimeLimit 无时长限制
    .withAttemptTimeLimiter(AttemptTimeLimiters.noTimeLimit())
    
    

    顾名思义,不限制执行时长;每次都是等执行任务执行完成之后,才进行后续的重试策咯。


    4.2 FixedAttemptTimeLimit
    .withAttemptTimeLimiter(AttemptTimeLimiters.fixedTimeLimit(10, TimeUnit.SECONDS));
    .withAttemptTimeLimiter(AttemptTimeLimiters.fixedTimeLimit(10, TimeUnit.SECONDS, Executors.newCachedThreadPool()));
    
    

    可以指定任务的执行时长限制,并且为了控制线程管理,最好指定相应的线程池。

    转自:https://www.jianshu.com/p/a289dde63043

    相关文章

      网友评论

          本文标题:guava-retrying 重试组件

          本文链接:https://www.haomeiwen.com/subject/xqvkzktx.html