翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
で再試行する AWS SDK for Kotlin
を呼び出すと、予期しない例外が返される AWS のサービス ことがあります。呼び出しを再試行すると、スロットリングや一時的なエラーなど、特定のタイプのエラーが成功する可能性があります。
このページでは、 が自動的に再試行 AWS SDK for Kotlin を処理する方法と、アプリケーションの再試行動作をカスタマイズする方法について説明します。
再試行動作について
以下のセクションでは、SDK がリクエストを再試行するタイミングを決定する方法と、再試行可能と見なされる例外について説明します。
デフォルトの再試行設定
デフォルトでは、すべてのサービスクライアントは標準の再試行戦略で自動的に設定されます。デフォルト設定では、最大 3 回失敗する呼び出しを試行します (最初の試行と 2 回の再試行)。各呼び出し間の介入遅延は、再試行ストームを回避するために、エクスポネンシャルバックオフとランダムジッターで設定されます。この設定は、ほとんどのユースケースで機能しますが、高スループットシステムなどの状況では適さない場合があります。
SDK は、再試行可能なエラーに対してのみ再試行を試みます。再試行可能なエラーの例としては、ソケットタイムアウト、サービス側のスロットリング、同時実行またはオプティミスティックロックの失敗、一時的なサービスエラーなどがあります。欠落または無効なパラメータ、認証/セキュリティエラー、設定ミスの例外は再試行可能と見なされません。
最大試行回数、遅延とバックオフ、トークンバケットの設定を設定することで、標準の再試行戦略をカスタマイズできます。
どの例外を再試行できますか?
は、再試行可能な例外を決定する事前設定された再試行ポリシー AWS SDK for Kotlin を使用します。サービスクライアント設定には、再試行に適用されるポリシーを指定するretryPolicyプロパティがあります。カスタム値を指定しない場合、デフォルト値は AwsRetryPolicy です。
以下の例外は、 によって再試行可能であると判断されますAwsRetryPolicy。
エラーコードで再試行可能
sdkErrorMetadata.errorCode 以下の ServiceExceptionを持つ :
BandwidthLimitExceededEC2ThrottledExceptionIDPCommunicationErrorLimitExceededExceptionPriorRequestNotCompleteProvisionedThroughputExceededExceptionRequestLimitExceededRequestThrottledRequestThrottledExceptionRequestTimeoutRequestTimeoutExceptionSlowDownThrottledExceptionThrottlingThrottlingExceptionTooManyRequestsExceptionTransactionInProgressException
HTTP ステータスコードで再試行可能
sdkErrorMetadata.statusCode 以下の ServiceExceptionを持つ :
500 (内部サービスエラー)
502 (不正なゲートウェイ)
503 (サービス利用不可)
504 (ゲートウェイタイムアウト)
エラータイプで再試行可能
sdkErrorMetadata.errorType 以下の ServiceExceptionを持つ 。
ErrorType.Server(内部サービスエラーなど)ErrorType.Client(無効なリクエスト、リソースが見つからない、アクセスが拒否されたなど)
SDK メタデータで再試行可能
以下のSdkBaseException場合:
sdkErrorMetadata.isRetryableはtrue(クライアント側のタイムアウト、ネットワーク/ソケットエラーなど)sdkErrorMetadata.isThrottlingはtrue(短時間にリクエストが多すぎるなど)
各サービスクライアントによってスローされる可能性のある例外の完全なリストについては、サービス固有の API リファレンスドキュメントを参照してください。
例外が再試行可能かどうかを確認します。
SDK が例外を再試行可能と見なすかどうかを判断するには、キャッチされた例外の isRetryableプロパティを確認します。
try { dynamoDbClient.putItem { tableName = "MyTable" item = mapOf("id" to AttributeValue.S("123")) } } catch (e: SdkBaseException) { println("Exception occurred: ${e.message}") if (e.sdkErrorMetadata.isRetryable) { println("This exception is retryable - SDK will automatically retry") println("If you're seeing this, retries may have been exhausted") } else { println("This exception is not retryable - fix the underlying issue") // Common non-retryable scenarios. when { e.message?.contains("ValidationException") == true -> println("Check your request parameters") e.message?.contains("AccessDenied") == true -> println("Check your IAM permissions") e.message?.contains("ResourceNotFound") == true -> println("Verify the resource exists") } } }
再試行が失敗した場合にコードに到達する例外
SDK の再試行メカニズムが問題を解決できない場合、例外はアプリケーションコードにスローされます。これらの例外タイプを理解することで、適切なエラー処理を実装できます。これらは再試行をトリガーする例外ではなく、 SDK によって内部的に処理されます。
再試行が枯渇または無効になると、コードは次のタイプの例外をキャッチします。
- 再試行後のサービス例外
-
すべての再試行が失敗すると、コードは最後の再試行が失敗する原因となった最終的なサービス例外 ( のサブクラス
AwsServiceException) をキャッチします。これは、スロットリングエラー、サーバーエラー、または SDK が再試行によって解決できなかったその他のサービス固有の例外である可能性があります。 - 再試行後のネットワーク例外
-
再試行のたびにネットワークの問題が解決されない場合、コードは接続タイムアウト、DNS 解決の失敗、SDK が解決できなかったその他の接続の問題など、
ClientExceptionインスタンスを検出します。
アプリケーションでこれらの例外を処理するには、次のパターンを使用します。
try { s3Client.getObject { bucket = "amzn-s3-demo-bucket" key = "my-key" } } catch (e: AwsServiceException) { // Service-side errors that persisted through all retries. println("Service error after retries: ${e.errorDetails?.errorCode} - ${e.message}") // Handle specific service errors that couldn't be resolved. if (e.errorDetails?.errorCode == "ServiceQuotaExceededException" || e.errorDetails?.errorCode == "ThrottlingException") { println("Rate limiting persisted - consider longer delays or quota increase") } } catch (e: ClientException) { // Client-side errors (persistent network issues, DNS resolution failures, etc.) println("Client error after retries: ${e.message}") }
再試行動作のカスタマイズ
以下のセクションでは、特定のユースケースに合わせて SDK の再試行動作をカスタマイズする方法を示します。
最大試行回数を設定する
クライアントの構築中に retryStrategyDSL ブロックのデフォルトの最大試行回数 (3) をカスタマイズできます。
val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { maxAttempts = 5 } }
前のスニペットで示した DynamoDB サービスクライアントでは、SDK は最大 5 回失敗する API コールを試行します (最初の試行と 4 回の再試行)。
次のスニペットに示すように、最大試行回数を 1 に設定することで、自動再試行を完全に無効にできます。
val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { maxAttempts = 1 // The SDK makes no retries. } }
遅延とバックオフを設定する
再試行が必要な場合、デフォルトの再試行戦略は後続の試行を行う前に待機します。最初の再試行の遅延は小さいですが、後の再試行では指数関数的に増加します。最大遅延量は、大きくなりすぎないように制限されます。
最後に、すべての試行間の遅延にランダムジッターが適用されます。ジッターは、再試行ストームを引き起こす可能性のある大規模なフリートの影響を軽減するのに役立ちます。(エクスポネンシャルバックオフとジッターの詳細については、このAWS アーキテクチャブログの投稿
遅延パラメータは delayProviderDSL ブロックで設定できます。
val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { delayProvider { initialDelay = 100.milliseconds maxBackoff = 5.seconds } } }
前のスニペットに示されている設定では、クライアントは最初の再試行を最大 100 ミリ秒遅延します。再試行間の最大時間は 5 秒です。
遅延とバックオフの調整には、次のパラメータを使用できます。
| パラメータ | デフォルト値 | 説明 |
|---|---|---|
initialDelay |
10 ミリ秒 | 最初の再試行の最大遅延時間。ジッターを適用すると、実際の遅延量が少なくなる可能性があります。 |
jitter |
1.0 (フルジッター) |
計算された遅延をランダムに減らす最大振幅。デフォルト値の 1.0 は、計算された遅延を最大 100% (0 など) まで減らすことができることを意味します。値 0.5 は、計算された遅延を最大半分に減らすことができることを意味します。したがって、最大遅延 10 ミリ秒を 5 ミリ秒から 10 ミリ秒の範囲で短縮できます。値 0.0 は、ジッターが適用されないことを意味します。 重要️ジッター設定は高度な機能です。この動作のカスタマイズは通常お勧めしません。 |
maxBackoff |
20 秒 | 試行に適用される最大遅延時間。この値を設定すると、その後の試行の間に発生する指数関数的な増加が制限され、計算された最大値が大きすぎることが防止されます。このパラメータは、ジッターが適用されるまでの計算遅延を制限します。適用されると、ジッターによって遅延がさらに減少する可能性があります。 |
scaleFactor |
1.5 | 後続の最大遅延が増加する指数ベース。たとえば、
|
再試行トークンバケットを設定する
デフォルトのトークンバケット設定を調整することで、標準の再試行戦略の動作をさらに変更できます。再試行トークンバケットは、成功する可能性が低い再試行や、タイムアウトやスロットリングの失敗など、解決に時間がかかる再試行を減らすのに役立ちます。
重要
トークンバケット設定は高度な機能です。この動作のカスタマイズは通常お勧めしません。
再試行するたびに (オプションで最初の試行を含む)、トークンバケットから一部の容量が減少します。減少する量は、試行のタイプによって異なります。例えば、一時的なエラーを再試行すると安くなりますが、タイムアウトまたはスロットリングエラーを再試行するとコストが高くなる可能性があります。
試行が成功すると、バケットに容量が返されます。バケットは最大容量を超えて増分したり、ゼロ未満に減らしたりすることはできません。
useCircuitBreakerMode 設定の値に応じて、 は容量をゼロ未満に減らそうとすると、次のいずれかの結果になります。
-
設定が TRUE の場合、例外がスローされます。たとえば、再試行回数が多すぎて、それ以上の再試行が成功する可能性が低い場合などです。
-
設定が FALSE の場合、遅延が発生します。たとえば、バケットが再び十分な容量になるまで遅延します。
注記
サーキットブレーカーがアクティブになると (トークンバケットが容量ゼロに達すると)、SDK は「再試行容量超過」というメッセージClientExceptionとともに をスローします。これは、 AWS サービスではなく SDK の再試行ロジックから発生するためAwsServiceException、 ではなくクライアント側の例外です。この例外は、 オペレーションを試行せずにすぐにスローされるため、サービス停止中の再試行ストームを防ぐことができます。
トークンバケットパラメータは tokenBucketDSL ブロックで設定できます。
val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy { tokenBucket { maxCapacity = 100 refillUnitsPerSecond = 2 } } }
再試行トークンバケットのチューニングには、次のパラメータを使用できます。
| パラメータ | デフォルト値 | 説明 |
|---|---|---|
initialTryCost |
0 | 最初の試行でバケットから減らす量。デフォルト値の 0 は、容量が減り、最初の試行が停止または遅延しないことを意味します。 |
initialTrySuccessIncrement |
1 | 最初の試行が成功したときの容量の増加量。 |
maxCapacity |
500 | トークンバケットの最大容量。使用可能なトークンの数はこの数を超えることはできません。 |
refillUnitsPerSecond |
0 | 1 秒ごとにバケットに再追加された容量。値 0 は、容量が自動的に再追加されないことを意味します。(たとえば、試行が成功すると容量が増加します)。値 0 は TRUE useCircuitBreakerModeである必要があります。 |
retryCost |
5 | 一時的な障害後に試行するためにバケットから減少する量。試行が成功すると、同じ量がバケットに再増分されます。 |
timeoutRetryCost |
10 | タイムアウトまたはスロットリングの失敗後に試行するためにバケットから減少する量。試行が成功すると、同じ量がバケットに再増分されます。 |
useCircuitBreakerMode |
正 | 容量を減らそうとすると、バケットの容量がゼロを下回る場合の動作を決定します。TRUE の場合、トークンバケットは再試行容量が存在しないことを示す例外をスローします。FALSE の場合、トークンバケットは十分な容量が補充されるまで試行を遅らせます。 |
サーキットブレーカーの例外など、再試行シナリオ中にスローされる例外タイプの詳細については、「」を参照してください再試行が失敗した場合にコードに到達する例外。
アダプティブ再試行を設定する
標準の再試行戦略の代わりに、アダプティブ再試行戦略は、スロットリングエラーを最小限に抑えるための理想的なリクエストレートを求める高度なアプローチです。
重要
アダプティブ再試行は高度な再試行モードです。この再試行戦略を使用することは通常お勧めしません。
アダプティブ再試行には、標準再試行のすべての機能が含まれています。これにより、スロットリングされていないリクエストと比較したスロットリングされたリクエストのレートを測定するクライアント側のレートリミッターが追加されます。また、トラフィックが安全な帯域幅内にとどまるように制限し、スロットリングエラーが発生するのが理想的です。
レートは、サービス条件やトラフィックパターンの変化にリアルタイムで適応し、それに応じてトラフィックのレートを増減する可能性があります。クリティカルなことに、レートリミッターはトラフィックの多いシナリオでの最初の試行を遅らせる可能性があります。
retryStrategy メソッドに追加のパラメータを指定して、アダプティブ再試行戦略を選択します。レートリミッターパラメータは rateLimiterDSL ブロックで設定できます。
val dynamoDb = DynamoDbClient.fromEnvironment { retryStrategy(AdaptiveRetryStrategy) { maxAttempts = 10 rateLimiter { minFillRate = 1.0 smoothing = 0.75 } } }
注記
アダプティブ再試行戦略では、クライアントが 1 つのリソース (1 つの DynamoDB テーブルまたは 1 つの Amazon S3 バケットなど) に対して動作することを前提としています。
1 つのクライアントを複数のリソースに使用すると、1 つのリソースに関連付けられたスロットリングまたは停止により、クライアントが他のすべてのリソースにアクセスするときにレイテンシーが増加し、障害が発生します。アダプティブ再試行戦略を使用する場合は、リソースごとに 1 つのクライアントを使用することをお勧めします。