使用resilience4j-retry實現函式呼叫重試

banq發表於2018-12-08

Resilience4j中有一個特殊模組(Resilience4j -Retry),它是為Java8和函數語言程式設計設計的容錯庫,它是具有最小依賴性的輕量級庫(主要是vavr) 

當你重試時,有很多例子:
  • 用於遠端系統呼叫的跨微服務通訊,其中很可能還需要新增斷路器邏輯
  • 如果您有業務或功能邏輯需要獲得一致的結束狀態,並且很可能是非同步


好的,你需要做什麼才能開始使用resileience4j重試:
如果你使用maven:

<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-retry</artifactId>
    <version>0.13.2</version>
</dependency>
<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-core</artifactId>
    <version>0.13.2</version>
</dependency>


重試模組可以有以下功能:
  • 同步重試和非同步重試
  • 關於異常或響應謂詞的Rety,如果您想要重試特定的響應值而不僅僅是丟擲異常,這可能很有用
  • 重試配置的退避策略加上最大重試次數
  • 忽略不重試的異常集
  • 它支援checked(新增了異常處理)和未檢查的函式執行(ex Function,Supplier,Callable,Runnable ..)
  • 如果需要,它可以與spring整合。


如何配置非同步重試,在Github上測試resilience4j重試的完整程式碼:

// Given the HelloWorldService returns Hello world
given(helloWorldService.returnHelloWorld())
    .willReturn(completedFuture("Hello world"));

final AsyncRetry retryContext = AsyncRetry.of("retryConfig",
        // we set the response type to String
        RetryConfig.<String>custom()
                // max retry attempts
                .maxAttempts(3)
                // what are the ignore exception to no retry on
                .ignoreExceptions(IllegalStateException.class)
                // what are the exceptions to try on
                .retryExceptions(TimeoutException.class)
                // retry if the response contains world
                .retryOnResult(s -> s.contains("world"))
                // retry backoff strategy, IntervalFunction has many built in interface functions you can check it out
                .intervalFunction(IntervalFunction.ofExponentialBackoff())
                .build());

// Decorate the invocation of the HelloWorldService
Supplier<CompletionStage<String>> supplier = AsyncRetry.decorateCompletionStage(
            retryContext,
            scheduler,
            () -> helloWorldService.returnHelloWorld());

// When
String result = awaitResult(supplier);
// Then the helloWorldService should be invoked 1 time
BDDMockito.then(helloWorldService).should(Mockito.times(3)).returnHelloWorld();
Assertions.assertEquals(result, "Hello world");


對於同步呼叫,您有許多選項(Supplier , Callable , Function 。。)

// Given the HelloWorldService returns Hello world
BDDMockito.given(helloWorldService.returnHelloWorld()).willReturn("Hello world");
// Create a Retry with default configuration
final RetryConfig tryAgain = RetryConfig.<String>custom().retryOnResult(s -> s.contains("Hello world"))
                .maxAttempts(2).build();
Retry retry = Retry.of("id", tryAgain);
// Decorate the invocation of the HelloWorldService
Supplier<String> supplier = Retry.decorateSupplier(retry, helloWorldService::returnHelloWorld);
// When
String result = supplier.get();
// Then the helloWorldService should be invoked 1 time
BDDMockito.then(helloWorldService).should(Mockito.times(2)).returnHelloWorld();
assertThat(result).isEqualTo("Hello world");





 

相關文章