guava-retry

2020-06-06  本文已影响0人  愤怒的老照

背景

之前很少接触需要重试的东西,失败后直接抛异常。但是接触过分布式锁以后,未获取锁的异常属于正常现象,需要我们捕获后重试,经过设定的重试次数后如果再抛异常,就直接抛给上层。

实现1

第一种方法是直接在代码使用循环来实现重试。

public void test(RegisterParam registerParam){
        int times  = 3;
        for (int i=0;i<times;i++) {
            try {
                this.registerWithRetry(registerParam);
                break;
            } catch (InterruptedException e) {
                // 重试
            } catch (ServiceException e) {
                // 重试
            }
        }
    }

正常逻辑和重试逻辑强耦合,重试逻辑非常依赖正常逻辑的执行结果,对正常逻辑预期结果被动重试触发,对于重试根源往往由于逻辑复杂被淹没,可能导致后续运维对于重试逻辑要解决什么问题产生不一致理解。重试正确性难保证而且不利于运维,原因是重试设计依赖正常逻辑异常或重试根源的臆测。

设计模式实现重试

上面的一个问题就是正常的逻辑和重试代码强耦合在一起,可以通过命令模式来解耦。将要执行的业务抽象成一个命令,将命令传到Retry里,不需要业务代码关心重试,可以实现解耦。

Guava-Retry

guava-retry是guava提供的重试机制,使用起来很简单

引入pom

<guava-retry.version>2.0.0</guava-retry.version>
<dependency>
      <groupId>com.github.rholder</groupId>
      <artifactId>guava-retrying</artifactId>
      <version>${guava-retry.version}</version>
</dependency>

构造重试对象

Retryer<Boolean> retryer = RetryerBuilder
                .<Boolean>newBuilder()
                 // 如果结果是false,重试
                .retryIfResult(Predicates.equalTo(false))
                 // 本次尝试失败后,过3秒再次尝试
                .withWaitStrategy(WaitStrategies.fixedWait(3, TimeUnit.SECONDS))
                // 总共尝试3次
                .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                // 遇到运行时异常才重试
                .retryIfRuntimeException()
                .build();

使用

retryer.call(() -> this.registerWithRetry(registerParam));
上一篇下一篇

猜你喜欢

热点阅读