使用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次數會拋異常出來,如果有循環可能造成影響

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