異步回調實現- 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有更好的性能和更好的吞吐量-至少根據不一樣回退算法在不一樣重播機率下的性能比較。

相關文章
相關標籤/搜索