Java 8以降を対象とする軽量なフォールトトレランスライブラリであるFailsafeが、2021年11月、メジャーリリースとなる3.0をローンチした。このリリースでは、APIの一部が大きく変更され、新たなdev.failsafe
パッケージ、新しいMaven groupid
、すべてのポリシを対象とするビルダAPIが導入された他、Circuit Braker、Retry Policy、Standalone Execution、Async Executionなどのメソッドが再設計されている。
さらに、先日発表されたバージョン3.2では、Rate LimiterおよびBulkheadポリシが追加されている。
フェールセーフポリシは、最終的な障害の処理方法を決定するものだ。デフォルトではすべての例外が処理されるが、より特定の障害を対象とするようにカスタマイズすることも可能である。
Failsafeが現在サポートするレジリエンスポリシは次のようなものだ — リトライの実施を定義するRetry Policy、一時的に実行不能にすることでシステムのオーバーロードを回避するCircuit Brealer、実行の許可率を定義するRate Limiter、応答に長時間を要する場合の実行をキャンセルするTimeout、並列実行数を制限するBulkhead、実行失敗時に他の結果を提供するFallback。
サーキットブレーカはカウントベースと時間ベースの2パターンをサポートする。前者は失敗数を制限値までカウントするもので、後者は一定時間内の失敗数をカウントするものだ。
これらのポリシを組み合わせて、複雑な独自の動作を定義することもできる。
以下に示すコードスニペットは、複数のポリシを構成した例である。
Fallback<Object> fallback = Fallback.of(this::connectToBackup);
CircuitBreaker<Object> circuitBreaker = CircuitBreaker.ofDefaults();
Timeout<Object> timeout = Timeout.of(Duration.ofSeconds(10));
// Get with fallback, retries, circuit breaker, and timeout
Failsafe.with(fallback)
.compose(retryPolicy)
.compose(circuitBreaker)
.compose(timeout)
.get(this::connect);
機能の構成に従って、逆順にポリシが適用される。従って上記の例では、最初はtimeout
、次にcircultBreaker
、最後がretryPolicy
となる。
同期実行の他に、FailsafeはJavaのCompletableFuture
のような非同期コードにも統合することができる。以下にあげた例では、Async動作のすべてのステージにRetry Policyが適用される。
CompletableFuture.supplyAsync(() -> Failsafe.with(retryPolicy).get(() -> "foo"))
.thenApplyAsync(value -> Failsafe.with(retryPolicy).get(() -> value + "bar"))
.thenAccept(System.out::println);
Failsafeのコンセプトは、Netflix HystrixやResilience4Jなど他のツールと大きくは変わらない。一方で、他のツールと対照的なのは、Failsafeが外部ライブラリへの依存関係を持たないことだ。
Failsafeは特に、Eclipse MicroProfileやApache Samza、Apache Pulsar、Prestoといった、オープンソース界の重要なプレイヤによって使用されている。