異步回調實現- Guava Retryer


為什么要使用重試利器Retryer

在實際開發中我們經常會遇到需要輪詢查詢一個接果,實現輪詢的方式有很多種,我們經常要寫許多代碼,有時還會怕寫出的代碼有bug,如果已經有輪子了,我們就沒必要重復造輪子了,畢竟時間有限,我們要掙錢。

github上開源的重試利器: https://github.com/rholder/guava-retrying

此retry是結合了Callable接口來實現,重試功能的,話不多說,直接上碼。

重試利器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次;

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分鍾一次的頻率進行重試

有興趣的可參考 指數回退:https://en.wikipedia.org/wiki/Exponential_backoff

4.創建一個永久重試的重試器,在每次重試失敗后以遞增的退避間隔等待,直到最多2分鍾。 2分鍾后,每隔2分鍾重試一次

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有更好的性能和更好的吞吐量-至少根據不同回退算法在不同重播概率下的性能比較。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM