异步回调实现- Guava Retryer

为何要使用重试利器Retryer

在实际开发中咱们常常会遇到须要轮询查询一个接果,实现轮询的方式有不少种,咱们常常要写许多代码,有时还会怕写出的代码有bug,若是已经有轮子了,咱们就不必重复造轮子了,毕竟时间有限,咱们要挣钱。java

github上开源的重试利器: https://github.com/rholder/guava-retryinggit

此retry是结合了Callable接口来实现,重试功能的,话很少说,直接上码。github

重试利器maven配置

<dependency>
      <groupId>com.github.rholder</groupId>
      <artifactId>guava-retrying</artifactId>
      <version>2.0.0</version>
</dependency>

重试利器示例

1.若是想重试几回就结束轮询的话,可参考以下代码算法

package com.example.guava;

import com.github.rholder.retry.RetryException;
import com.github.rholder.retry.Retryer;
import com.github.rholder.retry.RetryerBuilder;
import com.github.rholder.retry.StopStrategies;
import com.google.common.base.Predicates;

import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;

/**
 * @author: GuanBin
 * @date: Created in 下午4:30 2019/11/3
 */
public class RetryTest {

    public static void main(String[] args) {
        //callable是定义具体的业务操做,并返回该操做结果的返回值
        Callable<Boolean> callable = new Callable<Boolean>() {
            public Boolean call() throws Exception {
                return true; // do something useful here
            }
        };

        //定义retryer,指定轮询条件,及结束条件
        Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
                .retryIfResult(Predicates.<Boolean>isNull())
                .retryIfExceptionOfType(IOException.class)
                .retryIfRuntimeException()
                .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                .build();
        try {
            retryer.call(callable);
        } catch (RetryException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

}

retryer的条件是,callable的返回值是null或者有io异常或者运行时异常,则进行重试,重试次数为3次;maven

2.若是想以每隔一段时间的频率重试可参考以下代码函数

  Retryer<TaskResult> getExecutionStatusRetryer = RetryerBuilder.<TaskResult>newBuilder()
                    .withWaitStrategy(WaitStrategies.fixedWait(5, TimeUnit.SECONDS))
                    .retryIfResult(r -> !Constants.completeStatus.contains(r.getStatus()))
                    .withStopStrategy(StopStrategies.neverStop())
                    .build();
WaitStrategies定义等待策略:示例是5秒一次就会轮询一次call的实现()
StopStrategies是定义中止轮询策略的,StopStrategies.neverStop() 若知足轮询条件的话,会一直进行重试下去

3.建立一个永久重试的重试器,在每次重试失败后以递增的指数退避间隔等待,直到最多5分钟。 5分钟后,每隔5分钟重试一次。性能

 Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
                .retryIfExceptionOfType(IOException.class)
                .retryIfRuntimeException()
                .withWaitStrategy(WaitStrategies.exponentialWait(100, 5, TimeUnit.MINUTES))
                .withStopStrategy(StopStrategies.neverStop())
                .build();

若第一次重试是100毫秒后重试,若进行第二次则是增长到200毫秒进行重试,依次类推,知道达到5分钟的上限,以后按照5分钟一次的频率进行重试ui

有兴趣的可参考 指数回退:https://en.wikipedia.org/wiki/Exponential_backoffgoogle

4.建立一个永久重试的重试器,在每次重试失败后以递增的退避间隔等待,直到最多2分钟。 2分钟后,每隔2分钟重试一次spa

Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
        .retryIfExceptionOfType(IOException.class)
        .retryIfRuntimeException()
        .withWaitStrategy(WaitStrategies.fibonacciWait(100, 2, TimeUnit.MINUTES))
        .withStopStrategy(StopStrategies.neverStop())
        .build();

与指数等待策略相似,FibonacciWaitStrategy遵循的模式是每次尝试失败后等待时间增长。

FibonacciWaitStrategy是用斐波那契数列来计算等待时间,而不是指数函数。根据目前实践中发现,fibonacciwaitstrategy可能比指数waitstrategy有更好的性能和更好的吞吐量-至少根据不一样回退算法在不一样重播几率下的性能比较。

相关文章
相关标签/搜索