使用guava-retrying进行网络请求重试初体验

起源

库存同步因为店铺-sku-spu-库存进行笛卡尔积,同步总数庞大,可能一天轮询一次。可能因为请求过于频繁,所以偶尔请求会报错,内容如下:
在这里插入图片描述

无法卡定时任务

  • 有的定时任务,比如生成发票这种,如果不成功,可以卡定时任务。原因是操作数量小,内容可控(数据可控,系统内可更改),短时间卡顿影响不大
  • 库存同步定时任务,因为多次笛卡尔积,涉及到库存量的问题,所以无法卡定时任务,不论结果如何,必须跑下去,此库存同步失败了,需进行后续的库存同步

造成后果

同步失败的库存,造成库存同步延迟,可能到第二天才会重试

解决方式

在这里插入图片描述

1.这是什么

百度得知这东西全名叫guava-retrying

2.java版本

在这里插入图片描述在这里插入图片描述

找到版本50,对应jdk1.6,OK,服务器JDK版本1.7,可以正常用

Retry的百度代码

Callable<Integer> task = new Callable<Integer>() {
    @Override
    public Integer call() throws Exception {
        return 2;
    }
};

Retryer<Integer> retryer = RetryerBuilder.<Integer>newBuilder()
        .retryIfResult(Predicates.<Integer>isNull())//为空就retry
        .retryIfResult(Predicates.equalTo(2))//为2就retry
        .retryIfExceptionOfType(IOException.class)//异常是IO异常就retry
        .withStopStrategy(StopStrategies.stopAfterAttempt(3))//最多retry3次
        .withWaitStrategy(WaitStrategies.fixedWait(3, TimeUnit.SECONDS))//重试等3秒
        .build();
try {
    retryer.call(task);
} catch (ExecutionException e) {
    e.printStackTrace();
} catch (RetryException e) {
    e.printStackTrace();
}

遇到的问题

retryIfResult现有的不满足要求,我要的是对象里面的字段值如果是false就retry,百度找不到解法,没办法看源码

retryIfResult

这句可以看出retryIfResult里面应该做了判断用于是否retry
在这里插入图片描述
在这里插入图片描述

可以看到这里调用了传入的Predicate的对象apply返回值,所以我们应该做个Predicate,里面包含apply方法,让它的返回值为true就会进行重试了

Predicates.equalTo(2)

这句可以看出Predicates应该是个工具类,用于创造Predicate对象,那就参考一下内部的Predicate,可以找到一个比较像的:
在这里插入图片描述
特别简单,做个枚举单例就可以了

####最终效果
在这里插入图片描述
这里注意到是否成功进行了取反,因为我这里请求成功的情况会返回true,不成功返回false。这种情况,希望不成功的结果进行重试,所以要取反

最终效果

Retryer<EsbPlatformResultVO> retryer = RetryerBuilder.<EsbPlatformResultVO>newBuilder()
                           .retryIfException()
                           .retryIfResult(CreateFaciltiyPredicate.INSTANCE)
                           .withWaitStrategy(WaitStrategies.fixedWait(5, TimeUnit.SECONDS))
                           .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                           .build();

EsbPlatformResultVO resultVO1=new EsbPlatformResultVO();
                    try{
                        resultVO1 = retryer.call(new CreateFacilityTask());
                    }catch (Exception e){
                        resultVO1.setSuccess(false);
                        resultVO1.setMessage("XXX");
                    }

public class CreateFacilityTask implements Callable<EsbPlatformResultVO> {
   
    public CreateFacilityTask(){
       
    }
    @Override
    public EsbPlatformResultVO call() throws Exception {
        EsbPlatformResultVO resultVO1 = doSomething();
//...此处代码按照自己需求来写
        return resultVO1;
    }
}

注意点:retryer.call要用try…catch包围,不然超过了retry次数会抛异常出来,如果有循环可能造成影响

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章