美文网首页
guava-retrying3 学习

guava-retrying3 学习

作者: 月巴大叔 | 来源:发表于2023-07-02 21:34 被阅读0次

使用场景

做自动化场景,对于一些数据统计,有时数据同步更新会遇到延迟的场景,延时的时间可能不确定,此时,如果用 sleep 一定时间的话,可能会造成时间的浪费。那么有什么方法了避免呢,比如使用重试机制,设置重试的时间和重试的次数,当获取不到数据时根据预定的时间来重新请求接口。

重试的实现的要素

  • 重试触发时机
  • 什么条件去停止
  • 重试等待时间
  • 重试停止条件
  • 接口请求时间限制
  • 如果结束
  • 重试时的监听

guava-retrying 策略介绍

  • ** retryIfException() **: 当发生任何异常时触发重试。
  • ** retryIfExceptionOfType(Class<? extends Throwable> exceptionType) ** : 当发生指定类型的异常时触发重试。
  • ** retryIfRuntimeException() **:当发生 RuntimeException 或其子类异常时触发重试。
  • ** retryIfResult(Predicate<R> resultPredicate) ** :根据返回结果的条件触发重试。可以使用自定义的 Predicate 对返回结果进行判断。
  • ** retryIfException(Predicate<Throwable> exceptionPredicate) **:根据异常的条件触发重试。可以使用自定义的 Predicate 对异常进行判断。
  • ** withStopStrategy(StopStrategy stopStrategy) **:配置停止策略,指定在何时停止重试。常用的停止策略包括:
  • ** StopStrategies.stopAfterAttempt(int maxAttempts) **:在达到最大尝试次数后停止重试。
  • ** StopStrategies.neverStop() **:永不停止重试,会一直进行重试
  • ** withWaitStrategy(WaitStrategy waitStrategy) **:配置等待策略,指定每次重试之间的等待时间。常用的等待策略包括:
    • ** WaitStrategies.fixedWait(long sleepTime, TimeUnit timeUnit) **:固定等待时间,每次重试之间等待指定的时间间隔。
    • ** WaitStrategies.randomWait(long minimumTime, long maximumTime, TimeUnit timeUnit) **:随机等待时间,每次重试之间等待随机的时间间隔。
  • ** withAttemptTimeLimiter(AttemptTimeLimiter<V> attemptTimeLimiter) **:配置重试时间限制器,用于限制每次重试的时间。可以使用 FixedAttemptTimeLimit、ExponentialAttemptTimeLimit 或自定义的时间限制器。
  • ** withRetryListener(RetryListener retryListener) **:添加重试监听器,用于在重试过程中触发相应的事件。可以实现 RetryListener 接口自定义监听器
  • ** withBlockStrategy() **:方法用于配置阻塞策略,指定在进行重试时的阻塞行为。阻塞策略定义了在重试之间是否需要进行阻塞等待,以及等待的方式和时长

构造一个 Retryer

Retryer<T> retryer = RetryerBuilder.<T>newBuilder()
                .retryIfException()
                // 自定义重试条件
                .retryIfExceptionOfType(NeedRetryException.class)
                //停止策略,最大尝试请求, attemptNumber次
                .withStopStrategy(StopStrategies.stopAfterAttempt(attemptNumber))
                //等待策略,每次请求间隔1s
                .withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.SECONDS))
                //尝试请求时间限制,不能超过 taskTime
                .withAttemptTimeLimiter(new FixedAttemptTimeLimit(taskTime, TimeUnit.SECONDS, Executors.newCachedThreadPool()))
                //方法用于配置阻塞策略,指定在进行重试时的阻塞行为
                .withBlockStrategy(spinBlockStrategy)
                //重试过程的监听策略,打印了尝试的次数
                .withRetryListener(new RetryListener() {
                    @Override
                    public <V> void onRetry(Attempt<V> attempt) {
                        log.info("尝试次数 " + attempt.getAttemptNumber());
                    }
                })
                .build();

尝试定义一个方法,使用 Callable 接口作为参数传入一个执行的任务

 public static <T> T retry(Callable<T> task, int attemptNumber, int sleepTime, int taskTime) throws Throwable {
        SpinBlockStrategy spinBlockStrategy = new SpinBlockStrategy();
        spinBlockStrategy.block(1);
        Retryer<T> retryer = RetryerBuilder.<T>newBuilder()
                .retryIfException()
                // 自定义重试条件
                .retryIfExceptionOfType(NeedRetryException.class)
                //停止策略,最大尝试请求, attemptNumber次
                .withStopStrategy(StopStrategies.stopAfterAttempt(attemptNumber))
                //等待策略,每次请求间隔1s
                .withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.SECONDS))
                //尝试请求时间限制,不能超过 taskTime
                .withAttemptTimeLimiter(new FixedAttemptTimeLimit(taskTime, TimeUnit.SECONDS, Executors.newCachedThreadPool()))
                //方法用于配置阻塞策略,指定在进行重试时的阻塞行为
                .withBlockStrategy(spinBlockStrategy)
                //重试过程的监听策略,打印了尝试的次数
                .withRetryListener(new RetryListener() {
                    @Override
                    public <V> void onRetry(Attempt<V> attempt) {
                        log.info("尝试次数 " + attempt.getAttemptNumber());
                    }
                })
                .build();
        try {
            return retryer.call(task);
        } catch (RetryException | ExecutionException e) {
            //throw inner exception
            String msg = "";
            log.error("retry internal error: {}", msg);
            throw new RuntimeException(msg);
        }
    }

guava-retrying3 结合testng使用,如果当我们Assert来作为判断任务的尝试条件时,有一个点需要注意,retry中的 call 方法最终抛出的对象为 throw new ExecutionError((Error)cause),这边 new 出了一个 com.google.common.util.concurrent.ExecutionError 类的对象。而不是 java.util 类的。因此,我们需要重写重试报错类型


image.png

代码中call的方法

retryer.call(task)

 private void wrapAndThrowRuntimeExecutionExceptionOrError(Throwable cause) {
        if (cause instanceof Error) {
            throw new ExecutionError((Error)cause);
        } else {
            throw new UncheckedExecutionException(cause);
        }
    }

相关文章

  • 学习学习学习

    第三天了,连续三天,早上睁眼开始,看视频,做课件,连续作业,直到晚上十二点才睡觉。吃饭不规律,想起来就吃,感觉不饿...

  • 学习学习学习

    23岁的我,才真正明白,什么是学习,什么是努力,努力和不努力真的不同,就好比同样是一篇稿子,我用一周背下来,有的人...

  • 学习学习学习!

    妈妈总是让我学习,我只能用装当办法。 方法一: 方法二: 方法三: 方法四: ...

  • 学习学习学习

    001.今天看财富自由之路看了第二遍,而且看了一半,算是完成任务很开心。中间有想放弃的念头,坚持看完。眼睛痛,一直...

  • 学习学习学习

    马自达为什么坚持高压缩比自吸

  • 学习!学习!学习!

    学习的痛苦是暂时的 没有学到的痛苦是永恒的 因为学习而特别充实的一天 很踏实 ~~~~ 2015.11.28.阴天...

  • 学习!学习!学习!

    无数次想要去逃离,可这封闭的世界根本出不去。你没有什么可以抛弃、只能咬着牙带着面具微笑的活下去。 没有那个人、他也...

  • 学习学习学习!

    昨天和今天两个上午,都在学习新媒体运营,学习的过程中心里只有一个想法:这也太套路,太功利了吧。可真应了那句话...

  • 学习,学习,学习!

    近期学习重点有两个方面,一方面是把上一个阶段定下任务的几本书读完,并在读的过程中有输出和转化,让阅读和学习真正能有...

  • 学习学习学习

    人不学习不长进,能放下自己的身段,以空杯心态去学习,就能有所收获。 今天在群里听大家讨论写作,这个...

网友评论

      本文标题:guava-retrying3 学习

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