SmallRye Fault Tolerance
マイクロサービスの分散した性質がもたらす課題の1つは、外部システムとの通信が本質的に信頼できないことです。これにより、アプリケーションの耐障害性に対する要求が高まります。より耐障害性の高いアプリケーションを簡単に作るために、Quarkusは MicroProfile Fault Tolerance仕様の実装である SmallRye Fault Toleranceを提供します。
このガイドでは、MicroProfile Fault Tolerance アノテーションである`@Timeout`、@Fallback
、@Retry
、@CircuitBreaker`および `@RateLimit
の使用方法を説明します。
要件
このガイドを完成させるには、以下が必要です:
-
約15分
-
IDE
-
JDK 17+がインストールされ、
JAVA_HOME
が適切に設定されていること -
Apache Maven 3.9.9
-
使用したい場合は、 Quarkus CLI
-
ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること
シナリオ
このガイドで構築されたアプリケーションは、グルメコーヒーのeショップのためのシンプルなバックエンドをシミュレートします。これは、店舗にあるコーヒーサンプルに関する情報を提供する REST エンドポイントを実装しています。
そのような実装はされていませんが、エンドポイントのいくつかのメソッドが、データベースや外部のマイクロサービスなどの外部サービスとの通信を必要とし、信頼性の低い要素を導入することを想像してみましょう。
ソリューション
次の章で紹介する手順に沿って、ステップを踏んでアプリケーションを作成することを推奨します。 ただし、完成した例にそのまま進むこともできます。
git clone https://github.com/quarkusio/quarkus-quickstarts.git
で Git リポジトリーをクローンします。または、https://github.com/quarkusio/quarkus-quickstarts/archive/main.zip[アーカイブ] をダウンロードします。
ソリューションは microprofile-fault-tolerance-quickstart
ディレクトリ にあります。
Maven プロジェクトの作成
まず、新しいプロジェクトが必要です。以下のコマンドで新規プロジェクトを作成します。
Windowsユーザーの場合:
-
cmdを使用する場合、(バックスラッシュ
\
を使用せず、すべてを同じ行に書かないでください)。 -
Powershellを使用する場合は、
-D
パラメータを二重引用符で囲んでください。例:"-DprojectArtifactId=microprofile-fault-tolerance-quickstart"
このコマンドはプロジェクトを生成し、Quarkus REST(旧RESTEasy Reactive)/Jakarta RESTおよびSmallRye Fault Toleranceのエクステンションをインポートします。
すでにQuarkusプロジェクトが設定されている場合は、プロジェクトのベースディレクトリーで以下のコマンドを実行することで、プロジェクトに smallrye-fault-tolerance
エクステンションを追加することができます。
quarkus extension add smallrye-fault-tolerance
./mvnw quarkus:add-extension -Dextensions='smallrye-fault-tolerance'
./gradlew addExtension --extensions='smallrye-fault-tolerance'
これにより、ビルドファイルに次の内容が追加されます。
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-fault-tolerance</artifactId>
</dependency>
implementation("io.quarkus:quarkus-smallrye-fault-tolerance")
アプリケーションの準備: RESTエンドポイントとCDIビーン
このセクションでは、後でフォールトトレランス機能を追加できるよう、拡張可能なようにアプリケーションの骨組を作成します。
まず、お店のコーヒーのサンプルを表すシンプルなエンティティを作成します。 :
package org.acme.microprofile.faulttolerance;
public class Coffee {
public Integer id;
public String name;
public String countryOfOrigin;
public Integer price;
public Coffee() {
}
public Coffee(Integer id, String name, String countryOfOrigin, Integer price) {
this.id = id;
this.name = name;
this.countryOfOrigin = countryOfOrigin;
this.price = price;
}
}
続いて、コーヒーのサンプルのrepositoryとして動作するシンプルなCDIビーンです。
package org.acme.microprofile.faulttolerance;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class CoffeeRepositoryService {
private Map<Integer, Coffee> coffeeList = new HashMap<>();
public CoffeeRepositoryService() {
coffeeList.put(1, new Coffee(1, "Fernandez Espresso", "Colombia", 23));
coffeeList.put(2, new Coffee(2, "La Scala Whole Beans", "Bolivia", 18));
coffeeList.put(3, new Coffee(3, "Dak Lak Filter", "Vietnam", 25));
}
public List<Coffee> getAllCoffees() {
return new ArrayList<>(coffeeList.values());
}
public Coffee getCoffeeById(Integer id) {
return coffeeList.get(id);
}
public List<Coffee> getRecommendations(Integer id) {
if (id == null) {
return Collections.emptyList();
}
return coffeeList.values().stream()
.filter(coffee -> !id.equals(coffee.id))
.limit(2)
.collect(Collectors.toList());
}
}
最後に、 org.acme.microprofile.faulttolerance.CoffeeResource
クラスを以下のように作成します。 :
package org.acme.microprofile.faulttolerance;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import org.jboss.logging.Logger;
@Path("/coffee")
public class CoffeeResource {
private static final Logger LOGGER = Logger.getLogger(CoffeeResource.class);
@Inject
CoffeeRepositoryService coffeeRepository;
private AtomicLong counter = new AtomicLong(0);
@GET
public List<Coffee> coffees() {
final Long invocationNumber = counter.getAndIncrement();
maybeFail(String.format("CoffeeResource#coffees() invocation #%d failed", invocationNumber));
LOGGER.infof("CoffeeResource#coffees() invocation #%d returning successfully", invocationNumber);
return coffeeRepository.getAllCoffees();
}
private void maybeFail(String failureLogMessage) {
if (new Random().nextBoolean()) {
LOGGER.error(failureLogMessage);
throw new RuntimeException("Resource failure.");
}
}
}
この時点で、コーヒーサンプルのリストを JSON 形式で表示する単一の REST メソッドを公開しています。 CoffeeResource#maybeFail()
メソッドにいくつかの障害を発生させるコードを導入したことに注意してください。これにより、リクエストの約 50 % で CoffeeResource#coffees()
エンドポイントメソッドに障害が発生します。
アプリケーションが動作することを確認してみましょう。次のようにQuarkusの開発サーバーを起動してください。 :
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
http://localhost:8080/coffee
をブラウザで開きます。いくつかのリクエストを行います(いくつかのリクエストは失敗することを想定しています)。少なくともいくつかのリクエストは、コーヒーサンプルのリストをJSONで表示してくれるはずです。残りのリクエストは、 CoffeeResource#maybeFail()
内で RuntimeException
をスローして失敗します。
おめでとうございます!(多少、信頼性に欠けるものの)Quarkusアプリケーションが完成しました!
レジリエンスの追加: リトライ
Quarkusの開発サーバーを稼働させ、IDEで以下のように CoffeeResource#coffees()
メソッドに @Retry
アノテーションを追加し、ファイルを保存します。
import org.eclipse.microprofile.faulttolerance.Retry;
...
public class CoffeeResource {
...
@GET
@Retry(maxRetries = 4)
public List<Coffee> coffees() {
...
}
...
}
ブラウザの更新を実行します。Quarkusの開発サーバーが自動的に変更を検出してアプリを再コンパイルしてくれるので、再起動する必要はありません。
もう何度か更新ボタンを押してください。実質的にすべてのリクエストが成功しているはずです。 CoffeeResource#coffees()
メソッドは、実際にはまだ約 50% の時間で失敗していますが、そのたびにプラットフォームは自動的に呼び出しを再試行します!
障害がまだ発生していることを確認するには、開発サーバーの出力をチェックします。ログメッセージは以下のようになっているはずです。 :
2019-03-06 12:17:41,725 INFO [org.acm.fau.CoffeeResource] (XNIO-1 task-1) CoffeeResource#coffees() invocation #5 returning successfully
2019-03-06 12:17:44,187 INFO [org.acm.fau.CoffeeResource] (XNIO-1 task-1) CoffeeResource#coffees() invocation #6 returning successfully
2019-03-06 12:17:45,166 ERROR [org.acm.fau.CoffeeResource] (XNIO-1 task-1) CoffeeResource#coffees() invocation #7 failed
2019-03-06 12:17:45,172 ERROR [org.acm.fau.CoffeeResource] (XNIO-1 task-1) CoffeeResource#coffees() invocation #8 failed
2019-03-06 12:17:45,176 INFO [org.acm.fau.CoffeeResource] (XNIO-1 task-1) CoffeeResource#coffees() invocation #9 returning successfully
呼び出しが失敗するたびに、すぐに別の呼び出しが成功するまで続いていることがわかります。4回のリトライを許可しているので、ユーザーが実際に失敗にさらされるためには、5回の呼び出しが連続して失敗する必要があります。これは起こりそうもないことです。
レジリエンスの追加: タイムアウト
では、MicroProfile Fault Toleranceには他に何があるのでしょうか。タイムアウトについて見てみましょう。
CoffeeResource
エンドポイントに以下の 2 つのメソッドを追加します。ここでもサーバーを再起動する必要はなく、コードを貼り付けてファイルを保存するだけです。
import org.eclipse.microprofile.faulttolerance.Timeout;
...
public class CoffeeResource {
...
@GET
@Path("/{id}/recommendations")
@Timeout(250)
public List<Coffee> recommendations(int id) {
long started = System.currentTimeMillis();
final long invocationNumber = counter.getAndIncrement();
try {
randomDelay();
LOGGER.infof("CoffeeResource#recommendations() invocation #%d returning successfully", invocationNumber);
return coffeeRepository.getRecommendations(id);
} catch (InterruptedException e) {
LOGGER.errorf("CoffeeResource#recommendations() invocation #%d timed out after %d ms",
invocationNumber, System.currentTimeMillis() - started);
return null;
}
}
private void randomDelay() throws InterruptedException {
Thread.sleep(new Random().nextInt(500));
}
}
いくつかの新しい機能を追加しました。ユーザーが現在見ているコーヒーに基づいて、関連するコーヒーをお勧めできるようにしたいのです。これは重要な機能ではなく、あれば望ましい機能です。システムに負荷がかかり、おすすめ情報を得るためのロジックの実行に時間がかかりすぎる場合は、むしろタイムアウトしておすすめ情報のないUIを表示したいと考えています。
なお、タイムアウトは250msに設定し、0~500msのランダムな人工的な遅延が CoffeeResource#recommendations()
メソッドに導入されたことに注意してください。
お使いのブラウザで http://localhost:8080/coffee/2/recommendations
にアクセスして、2、3回更新してください。
org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException
でいくつかのリクエストがタイムアウトになるはずです。タイムアウトにならなかったリクエストでは、JSONに2つのおすすめコーヒーサンプルが表示されます。
レジリエンスの追加: フォールバック
関連するコーヒーを入手するための代替手段(おそらくより迅速な方法)を提供することで、おすすめ機能をさらに改善しましょう。
CoffeeResource
にフォールバック・メソッドを、 CoffeeResource#recommendations()
メソッドに @Fallback
アノテーションを以下のように追加します。
import java.util.Collections;
import org.eclipse.microprofile.faulttolerance.Fallback;
...
public class CoffeeResource {
...
@Fallback(fallbackMethod = "fallbackRecommendations")
public List<Coffee> recommendations(int id) {
...
}
public List<Coffee> fallbackRecommendations(int id) {
LOGGER.info("Falling back to RecommendationResource#fallbackRecommendations()");
// safe bet, return something that everybody likes
return Collections.singletonList(coffeeRepository.getCoffeeById(1));
}
...
}
http://localhost:8080/coffee/2/recommendations
を何回も更新してください。 TimeoutException
はもう表示されないはずです。代わりに、タイムアウトが発生した場合、元のメソッドが返す2つのレコメンデーションではなく、フォールバックメソッド fallbackRecommendations()
にハードコードされた1つのレコメンデーションが表示されます。
フォールバックが本当に行われているかどうか、サーバーの出力を確認してください。 :
2020-01-09 13:21:34,250 INFO [org.acm.fau.CoffeeResource] (executor-thread-1) CoffeeResource#recommendations() invocation #1 returning successfully
2020-01-09 13:21:36,354 ERROR [org.acm.fau.CoffeeResource] (executor-thread-1) CoffeeResource#recommendations() invocation #2 timed out after 250 ms
2020-01-09 13:21:36,355 INFO [org.acm.fau.CoffeeResource] (executor-thread-1) Falling back to RecommendationResource#fallbackRecommendations()
フォールバックメソッドには、元のメソッドと同じパラメータが必要です。 |
レジリエンスの追加: サーキットブレーカー
サーキットブレーカーは,システムの一部が一時的に不安定になったときに,システム内で発生する障害の数を制限するのに有効です。サーキットブレーカーは、あるメソッドの成功と失敗を記録し、失敗したメソッドの割合が指定された閾値に達すると、サーキットブレーカーが 開き、それ以降のメソッドの呼び出しを一定時間ブロックします。
次のコードを CoffeeRepositoryService
ビーンに追加して、サーキットブレーカーの動作をデモできるようにします。 :
import java.util.concurrent.atomic.AtomicLong;
import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
...
public class CoffeeRepositoryService {
...
private AtomicLong counter = new AtomicLong(0);
@CircuitBreaker(requestVolumeThreshold = 4)
public Integer getAvailability(Coffee coffee) {
maybeFail();
return new Random().nextInt(30);
}
private void maybeFail() {
// introduce some artificial failures
final Long invocationNumber = counter.getAndIncrement();
if (invocationNumber % 4 > 1) { // alternate 2 successful and 2 failing invocations
throw new RuntimeException("Service failed.");
}
}
}
そして、以下のコードを CoffeeResource
のエンドポイントに注入します。 :
public class CoffeeResource {
...
@Path("/{id}/availability")
@GET
public Response availability(int id) {
final Long invocationNumber = counter.getAndIncrement();
Coffee coffee = coffeeRepository.getCoffeeById(id);
// check that coffee with given id exists, return 404 if not
if (coffee == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
try {
Integer availability = coffeeRepository.getAvailability(coffee);
LOGGER.infof("CoffeeResource#availability() invocation #%d returning successfully", invocationNumber);
return Response.ok(availability).build();
} catch (RuntimeException e) {
String message = e.getClass().getSimpleName() + ": " + e.getMessage();
LOGGER.errorf("CoffeeResource#availability() invocation #%d failed: %s", invocationNumber, message);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(message)
.type(MediaType.TEXT_PLAIN_TYPE)
.build();
}
}
...
}
もう一つの機能を追加しました。このアプリケーションは、私たちの店における、指定されたコーヒーの残りのパッケージの量を返すことができます(単なる乱数です)。
今回は、CDIビーンに人工的な失敗を導入しました。 CoffeeRepositoryService#getAvailability()
メソッドは、2回の成功と2回の失敗の呼び出しを交互に行うことになります。
また、@CircuitBreaker`アノテーションを追加し、`requestVolumeThreshold = 4`としました。`CircuitBreaker.failureRatio
はデフォルトで 0.5 で、 CircuitBreaker.delay
はデフォルトで 5 秒です。つまり、過去4回の起動のうち2回が失敗した場合にサーキットブレーカーが開き、5秒間その状態のままになります。
これを試すには、次のようにします。 :
-
ブラウザで
http://localhost:8080/coffee/2/availability
を開いて下さい。数字が返ってくるのが見えるでしょう。 -
リフレッシュすると、この2回目のリクエストが再び成功し、数字が返ってくるはずです。
-
さらに2回リフレッシュします。2回とも、"RuntimeException:Service failed." というテキストが表示されます。これは、
CoffeeRepositoryService#getAvailability()
によってスローされる例外です。 -
さらに数回更新します。長く待ちすぎていなければ、再び例外が表示されるはずですが、今回は "CircuitBreakerOpenException: getAvailability" となっています。この例外は、サーキットブレーカーが開き、
CoffeeRepositoryService#getAvailability()
メソッドが呼び出されなくなったことを示しています。 -
5秒後にサーキットブレーカーが閉じて、再び2回のリクエストを成功させるようになります。
レジリエンスの追加: 流量制御
これは SmallRye Fault Tolerance の追加機能であり、MicroProfile Fault Tolerance では指定されていません。 |
ある操作が過剰に実行されるのを防ぐために、流量制御 を使用できます。流量制御は、一定の時間枠内で許可される最大呼び出し回数を制限します。たとえば、流量制御を使用すると、あるメソッドが 1分間に最大 50 回までしか呼び出されないように制御できます。制限を超える呼び出しは拒否され、RateLimitException
型の例外がスローされます。
さらに、呼び出しと呼び出しの間の最小間隔を定義することもできます。たとえば、最小間隔が 1 秒の場合、最初の呼び出しから 500 ミリ秒後に 2 番目の呼び出しが行われた場合、制限を超えていなくても拒否されます。
流量制御は表面的にはバルクヘッド (同時実行制限) に似ていますが、実際はまったく異なります。バルクヘッドは、任意の時点で同時に発生する実行数を制限します。流量制御は、同時実行を考慮せずに、一定の時間枠内での実行数を制限します。
流量制御では、呼び出しと呼び出しの間で何らかの状態を維持する必要があります。たとえば、最近の呼び出し回数、最後の呼び出しのタイムスタンプなどです。この状態はシングルトンで、@RateLimit
アノテーションを使用する Bean のライフサイクルは関係ありません。
具体的には、流量制御の状態は、Bean クラス (java.lang.Class
) と、保護されたメソッドを表すメソッドオブジェクト (java.lang.reflect.Method
) の組み合わせによって一意に識別されます。
Quarkus 開発モードを実行し、IDE で次のように CoffeeResource#coffees()
メソッドに @RateLimit
アノテーションを追加してファイルを保存します。
import java.time.temporal.ChronoUnit;
import io.smallrye.faulttolerance.api.RateLimit;
...
public class CoffeeResource {
...
@GET
@RateLimit(value = 2, window = 10, windowUnit = ChronoUnit.SECONDS)
public List<Coffee> coffees() {
...
}
...
}
ブラウザーで更新を押してください。Quarkus 開発サーバーは自動的に変更を検出し、アプリケーションを再コンパイルするので、再起動する必要はありません。
さらに数回更新を押すことができます。10 秒間隔で 2 回のリクエストを実行すると、ログに次のようなエラーが表示されるようになります。
INFO [org.acm.mic.fau.CoffeeResource] (executor-thread-1) CoffeeResource#coffees() invocation #1 returning successfully
ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (executor-thread-1) HTTP Request to /coffee failed, error id: d3e59090-fd45-4c67-844e-80a8f7fa6ee0-4: io.smallrye.faulttolerance.api.RateLimitException: org.acme.microprofile.faulttolerance.CoffeeResource#coffees rate limit exceeded
at io.smallrye.faulttolerance.core.rate.limit.RateLimit.doApply(RateLimit.java:58)
at io.smallrye.faulttolerance.core.rate.limit.RateLimit.apply(RateLimit.java:44)
at io.smallrye.faulttolerance.FaultToleranceInterceptor.syncFlow(FaultToleranceInterceptor.java:255)
at io.smallrye.faulttolerance.FaultToleranceInterceptor.intercept(FaultToleranceInterceptor.java:182)
at io.smallrye.faulttolerance.FaultToleranceInterceptor_Bean.intercept(Unknown Source)
at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:30)
at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:27)
at org.acme.microprofile.faulttolerance.CoffeeResource_Subclass.coffees(Unknown Source)
at org.acme.microprofile.faulttolerance.CoffeeResource$quarkusrestinvoker$coffees_73d7590ab944adfa130e4ad57c30282f825b2d18.invoke(Unknown Source)
at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:599)
at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2516)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2495)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1521)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:11)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:11)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:1583)
@Fallback
が @RateLimit
とともに使用される場合、フォールバック設定に応じて、RateLimitException
が出力されると、フォールバックメソッドまたはハンドラーが呼び出されることがあります。
@Retry
を @RateLimit
と一緒に使用すると、各再試行はレート制限によって独立した呼び出しとして処理されます。RateLimitException
が出力された場合、再試行の設定方法に応じて実行が再試行されることがあります。
@CircuitBreaker
を @RateLimit
と一緒に使用すると、流量制御を適用する前にサーキットブレーカーがチェックされます。レート制限によって RateLimitException
が発生した場合、サーキットブレーカーの設定によっては、失敗としてカウントされることがあります。
ランタイム設定
application.properties
ファイルの中で、実行時にアノテーションパラメータをオーバーライドすることができます。
先ほどのリトライの例で言えば :
package org.acme;
import org.eclipse.microprofile.faulttolerance.Retry;
...
public class CoffeeResource {
...
@GET
@Retry(maxRetries = 4)
public List<Coffee> coffees() {
...
}
...
}
以下の設定項目により、 maxRetries
パラメータをオーバーライドして、リトライ回数を4回から6回に変更することができます。 :
quarkus.fault-tolerance."org.acme.CoffeeResource/coffees".retry.max-retries=6
# alternatively, a specification-defined property can be used
org.acme.CoffeeResource/coffees/Retry/maxRetries=6
Quarkus ネイティブの設定プロパティーの完全なセットについては、設定リファレンス で説明されています。 仕様定義の設定プロパティーは引き続きサポートされますが、Quarkus ネイティブ設定が優先されます。
まとめ
SmallRye Fault Toleranceは、ビジネスロジックの複雑さに影響を与えることなく、アプリケーションの耐障害性を向上させます。
Quarkusのフォールトトレランス機能を有効にするために必要なのは次の通りです。 :
-
quarkus-maven-plugin
でsmallrye-fault-tolerance
Quarkus エクステンションをプロジェクトに追加することです :CLIquarkus extension add smallrye-fault-tolerance
Maven./mvnw quarkus:add-extension -Dextensions='smallrye-fault-tolerance'
Gradle./gradlew addExtension --extensions='smallrye-fault-tolerance'
-
または、単に以下のMaven依存関係を追加するだけです:
pom.xml<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-smallrye-fault-tolerance</artifactId> </dependency>
build.gradleimplementation("io.quarkus:quarkus-smallrye-fault-tolerance")
関連情報
SmallRye Fault Toleranceには、ここに示した以外にも多くの機能があります。 これらの機能については、 SmallRye Fault Toleranceのドキュメント を参照してください。
Quarkusでは、SmallRye Fault Toleranceのオプション機能をすぐに使用することができます。
Mutinyがサポートされているので、非同期のメソッドは CompletionStage
だけでなく Uni
を返すことができます。
MicroProfile Context PropagationはFault Toleranceと統合されているので、既存のコンテキストは自動的に非同期メソッドに伝搬されます。
これは CDI リクエストコンテキストにも当てはまります。もしオリジナルのスレッドでアクティブであれば、新しいスレッドに伝搬されますが、もしそうでなければ、新しいスレッドはそれを持ちません。 これは MicroProfile Fault Tolerance 仕様に反しており、 MicroProfile Context Propagationがある場合、この要件は適用されるべきではないと考えています。コンテキスト伝搬の主な目的は、新しいスレッドが元のスレッドと同じコンテキストを持っていることを確認することにあります。 |
非互換モードはデフォルトで有効に指定されています。
この設定では、CompletionStage
(または Uni
) を返すメソッドに、@Asynchronous
または @AsynchronousNonBlocking
アノテーションなしで非同期フォールトトレランスが適用されます。
また、例外自体が何が起こるかを決定するのに不十分な場合、サーキットブレーカー、フォールバック、再試行によって例外原因チェーンが自動的に検査されることになります。
このモードは、非互換性は非常に小さいものの、MicroProfile Fault Tolerance仕様と互換性がありません。 完全な互換性を回復するには、このコンフィギュレーションプロパティを追加してください。 :
|
プログラムAPI は、宣言的なアノテーション・ベースのAPIと統合されています。 Guard
、 TypedGuard
、 @ApplyGuard
のAPIをすぐに使うことができます。
Kotlinのサポートがあるため(Kotlin用のQuarkusエクステンションを使用することが前提)、フォールトトレランスのアノテーションで suspend
関数を保護することができます。
メトリクスは自動的に検出され、統合されます。 アプリケーションでQuarkus Extension for Micrometerを使用している場合、SmallRye Fault ToleranceからMicrometerにメトリクスが送信されます。 アプリケーションがSmallRye Metrics用のQuarkusエクステンションを使用している場合、SmallRye Fault ToleranceはMicroProfile Metricsにメトリクスを送信します。 そうでない場合は、SmallRye Fault Toleranceのメトリクスは無効になります。
設定リファレンス
以下の "<identifier>"
:
-
"<classname>/<methodname>"
: メソッドごとの設定 -
"<classname>"
: クラスごとの設定 -
global
: グローバル設定 -
また、
@ApplyGuard
を通じて宣言的に使用される、プログラムで構築されたGuard
またはTypedGuard
を設定するための@Identifier
値になる場合もあります。 この場合、設定は作成時に適用され、最初の使用時に遅延実行されるため、Guard
/TypedGuard
はプログラムで 決して 使用してはならないことに注意してください。 この最初の使用は@ApplyGuard
を介して行う必要があります。そうでない場合、設定は無視されます。
ビルド時に固定された設定プロパティー。その他の設定プロパティーは、すべて実行時にオーバーライド可能です。
Configuration property |
型 |
デフォルト |
---|---|---|
Whether fault tolerance strategies are enabled. Note that Environment variable: Show more |
boolean |
|
Whether fault tolerance metrics are enabled. Environment variable: Show more |
boolean |
|
Whether SmallRye Fault Tolerance should be compatible with the MicroProfile Fault Tolerance specification. Environment variable: Show more |
boolean |
|
The name of the method to call before retrying. The method belongs to the same class as the guarded method. The method must have no parameters and return Environment variable: Show more |
string |
|
The name of the method to call on fallback. The method belongs to the same class as the guarded method. The method must have a signature matching the signature of the guarded method. Environment variable: Show more |
string |
|
Whether the Environment variable: Show more |
boolean |
|
The Environment variable: Show more |
string |
|
Whether the Environment variable: Show more |
boolean |
|
Whether the Environment variable: Show more |
boolean |
|
Whether the Environment variable: Show more |
boolean |
|
The class of the Environment variable: Show more |
||
Whether the Environment variable: Show more |
boolean |
|
The maximum number of concurrent invocations. Environment variable: Show more |
int |
|
The maximum number of queued asynchronous invocations. Asynchronous invocations are queued when the number of concurrent invocations in progress has already reached the maximum. Synchronous invocations are not queued at all and are rejected immediately. Environment variable: Show more |
int |
|
Whether the Environment variable: Show more |
boolean |
|
The delay after which an open circuit breaker will move to half-open. Environment variable: Show more |
長 |
|
The unit for Environment variable: Show more |
|
|
The exception types that are considered failures. Environment variable: Show more |
list of Class |
|
The ratio of failures within the rolling window that will move a closed circuit breaker to open. Environment variable: Show more |
double |
|
The size of the circuit breaker rolling window. Environment variable: Show more |
int |
|
The exception types that are not considered failures. Takes priority over Environment variable: Show more |
list of Class |
|
The number of successful executions that move a half-open circuit breaker to closed. Environment variable: Show more |
int |
|
Whether the Environment variable: Show more |
boolean |
|
The class of the Environment variable: Show more |
||
Whether the Environment variable: Show more |
boolean |
|
The multiplicative factor used when determining a delay between two retries. A delay is computed as Environment variable: Show more |
int |
|
The maximum delay between retries. Environment variable: Show more |
長 |
|
The unit for Environment variable: Show more |
|
|
Whether the Environment variable: Show more |
boolean |
|
The exception types that are considered failures and hence should trigger fallback. Environment variable: Show more |
list of Class |
|
The exception types that are not considered failures and hence should not trigger fallback. Takes priority over Environment variable: Show more |
list of Class |
|
The class of the Environment variable: Show more |
||
Whether the Environment variable: Show more |
boolean |
|
The maximum delay between retries. Environment variable: Show more |
長 |
|
The unit for Environment variable: Show more |
|
|
Whether the Environment variable: Show more |
boolean |
|
Minimum time between two consecutive invocations. If the time between two consecutive invocations is shorter, the second invocation is rejected. Environment variable: Show more |
長 |
|
The unit for Environment variable: Show more |
|
|
The type of type windows used for rate limiting. Environment variable: Show more |
|
|
The maximum number of invocations in a time window. Environment variable: Show more |
int |
|
The time window length. Environment variable: Show more |
長 |
|
The unit for Environment variable: Show more |
|
|
Whether the Environment variable: Show more |
boolean |
|
The exception types that are not considered failures and hence should not be retried. Takes priority over Environment variable: Show more |
list of Class |
|
The delay between retry attempts. Environment variable: Show more |
長 |
|
The unit for Environment variable: Show more |
|
|
The maximum jitter to apply for the delay between retry attempts. The actual delay will be in the interval Environment variable: Show more |
長 |
|
The unit for Environment variable: Show more |
|
|
The maximum duration for which to retry. Environment variable: Show more |
長 |
|
The unit for Environment variable: Show more |
|
|
The maximum number of retry attempts. Environment variable: Show more |
int |
|
The exception types that are considered failures and hence should be retried. Environment variable: Show more |
list of Class |
|
Whether the Environment variable: Show more |
boolean |
|
Class of the predicate that will be used to determine whether the invocation should be retried if the guarded method has thrown an exception. Environment variable: Show more |
|
|
Class of the predicate that will be used to determine whether the invocation should be retried if the guarded method has returned a result. Environment variable: Show more |
|
|
Whether the Environment variable: Show more |
boolean |
|
The unit for Environment variable: Show more |
|
|
The timeout to enforce. Environment variable: Show more |
長 |
|
仕様定義のプロパティーが Quarkus ネイティブ設定にマッピングされる方法は次のとおりです。
仕様定義の設定プロパティー | Quarkus ネイティブ設定プロパティー |
---|---|
|
|
|
|
|
|
|
|
|
|
すべての <annotation> ` および `<member> ` の部分は、キャメルケース (`BeforeRetry
、methodName
) からケバブケース (before-retry
、method-name
) に変更されます。
一貫性を向上させるために、2 つのアノテーションメンバーが特別に処理されます。
-
Retry/durationUnit
はretry.max-duration-unit
に -
Retry/jitterDelayUnit
はretry.jitter-unit
に変更されます。