

# REL05-BP05 クライアントタイムアウトを設定する
<a name="rel_mitigate_interaction_failure_client_timeouts"></a>

接続とリクエストにタイムアウトを適切に設定し、体系的に検証します。また、デフォルト値には依存しないでください。これらはワークロードの詳細を認識していないためです。

 **期待される成果:** クライアントのタイムアウトには、完了までに異常に時間がかかるリクエストを待つことに関連するクライアント、サーバー、およびワークロードにかかるコストを考慮する必要があります。タイムアウトの正確な原因を知ることはできないため、クライアントはサービスの知識を活用して、考えられる原因と適切なタイムアウトを予測する必要があります。

 クライアント接続は、設定された値に基づいてタイムアウトします。タイムアウトが発生すると、クライアントはバックオフして再試行するか[サーキットブレーカー](https://martinfowler.com/bliki/CircuitBreaker.html)を開くか、いずれかを決定します。これらのパターンは、根本的なエラー状態を悪化させる可能性のあるリクエストの発行を回避します。

 **一般的なアンチパターン:** 
+  システムタイムアウトまたはデフォルトタイムアウトを認識していない。
+  通常のリクエスト完了タイミングを認識していない。
+  リクエストが完了するまでに異常に時間がかかる原因や、これらの完了を待つことによってクライアント、サービス、またはワークロードのパフォーマンスが低下する原因を認識していない。
+  ネットワークに障害が発生して、タイムアウトに達したときだけリクエストが失敗する確率や、より短いタイムアウトを採用しないことでクライアントとワークロードのパフォーマンスにコストがかかることを認識していない。
+  接続とリクエストの両方のタイムアウトシナリオはテストされていません。
+  タイムアウトの設定が高すぎると、待機時間が長くなり、リソースの使用率が高くなる可能性があります。
+  タイムアウトの設定が低すぎると、人為的な障害が発生します。
+  サーキットブレーカーや再試行などのリモート呼び出しのタイムアウトエラーを処理するパターンを見落としています。
+  サービス呼び出しエラー率、遅延に関するサービスレベル目標、および遅延異常値のモニタリングは考慮していません。これらのメトリクスから、タイムアウトが積極的または許容範囲が広いかを判断できます。

 **このベストプラクティスを活用するメリット:** リモート呼び出しのタイムアウトは、リモート呼び出しの応答が異常に遅い場合やタイムアウトエラーがサービスクライアントによって適切に処理される場合にリソースを節約できるように、タイムアウトを適切に処理するように設定され、システムがタイムアウトを適切に処理するように設計されています。

 **このベストプラクティスを活用しない場合のリスクレベル:** 高 

## 実装のガイダンス
<a name="implementation-guidance"></a>

 サービス依存関係呼び出しに接続タイムアウトとリクエストタイムアウトの両方を設定します。またこの設定は、通常プロセス全体のすべての呼び出しにも行います。多くのフレームワークにはタイムアウト機能が組み込まれていますが、デフォルト値が無限であるか、サービス目標の許容範囲を超えているものもあるので注意してください。値が高すぎると、クライアントがタイムアウトの発生を待機している間もリソースが消費され続けるため、タイムアウトの有用性が低下します。値が小さすぎると、再試行されるリクエストが多くなりすぎるため、バックエンドのトラフィックが増加し、レイテンシーが高くなってしまいます。場合によっては、すべてのリクエストが再試行されることになるため、完全な機能停止につながる恐れもあります。

 タイムアウト戦略を決定する際には、次の点を考慮してください。
+  リクエストの内容、ターゲットサービスの障害、またはネットワークパーティションの障害により、リクエストの処理に通常よりも時間がかかる場合があります。
+  異常に高価なコンテンツを含むリクエストは、サーバーとクライアントのリソースを不必要に消費する可能性があります。この場合、これらのリクエストをタイムアウトさせて再試行しないことで、リソースを節約できます。また、サービスは、スロットルやサーバー側のタイムアウトにより、異常にコストが大きいコンテンツから身を守る必要があります。
+  サービスの障害により異常に時間がかかるリクエストは、タイムアウトして再試行できます。リクエストと再試行のサービスコストを考慮する必要がありますが、原因が局所的な障害である場合は、再試行してもコストはかからず、クライアントリソースの消費量を削減できます。障害の性質によっては、タイムアウトによってサーバーリソースが解放されることもあります。
+  リクエストまたはレスポンスがネットワークから配信されなかったために完了までに時間がかかるリクエストは、タイムアウトして再試行できます。リクエストまたはレスポンスが配信されなかったため、タイムアウトの長さに関係なく失敗に終わったことになります。この場合、タイムアウトしてもサーバーリソースは解放されませんが、クライアントリソースが解放され、ワークロードのパフォーマンスが向上します。

 再試行やサーキットブレーカーなどの確立された設計パターンを活用して、タイムアウトをスムーズに処理し、フェイルファストアプローチをサポートします。[AWSSDK](https://docs.aws.amazon.com/index.html#sdks) と [AWS CLI](https://aws.amazon.com/cli/) を使用すると、接続タイムアウトとリクエストタイムアウトの両方を設定でき、エクスポネンシャルバックオフとジッターによる再試行も行えます。[AWS Lambda](https://aws.amazon.com/lambda/) 関数はタイムアウトの設定をサポートしており、[AWS Step Functions](https://aws.amazon.com/step-functions/) を併用すれば、ローコードのサーキットブレーカーを構築して、AWS サービスおよび SDK との事前構築済みの統合を活用できます。[AWS App Mesh](https://aws.amazon.com/app-mesh/)Envoy はタイムアウトとサーキットブレーカーの機能を備えています。

## 実装手順
<a name="implementation-steps"></a>
+  リモートサービス呼び出しのタイムアウトを設定し、組み込みの言語タイムアウト機能またはオープンソースのタイムアウトライブラリを活用してください。
+  ワークロードが AWS SDK を使用して呼び出しを行う場合は、ドキュメントで言語固有のタイムアウト設定を確認してください。
  + [Python](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html)
  + [PHP](https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.DefaultsMode.Configuration.html)
  + [.NET](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/retries-timeouts.html)
  + [Ruby](https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/timeout-duration.html)
  + [Java](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/best-practices.html#bestpractice5)
  + [Go](https://aws.github.io/aws-sdk-go-v2/docs/configuring-sdk/retries-timeouts/#timeouts)
  + [Node.js](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html)
  + [C\+\+](https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/client-config.html)
+  ワークロードで AWS SDK または AWS CLI コマンドを使用するときは、`connectTimeoutInMillis` と `tlsNegotiationTimeoutInMillis` の AWS [設定デフォルト](https://docs.aws.amazon.com/sdkref/latest/guide/feature-smart-config-defaults.html) を設定し、デフォルトのタイムアウト値を設定します。
+  [コマンドラインオプション](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html) の `cli-connect-timeout` と `cli-read-timeout` を適用して、AWS のサービスの 1 回限りの AWS CLI コマンドを制御します。
+  リモートサービス呼び出しのタイムアウトをモニタリングし、エラーが続く場合はアラームを設定して、エラーシナリオにプロアクティブに対処できるようにします。
+  コールエラー率、レイテンシーに関するサービスレベル目標、レイテンシーの外れ値に関する [CloudWatch メトリクス](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/working_with_metrics.html)と [CloudWatch 異常検出](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Anomaly_Detection.html)を実装すると、過度にアグレッシブなタイムアウトや許容範囲のタイムアウトの管理に関するインサイトが得られます。
+  [Lambda 関数](https://docs.aws.amazon.com/lambda/latest/dg/configuration-function-common.html#configuration-timeout-console)でタイムアウトを設定します。
+  API Gateway クライアントは、タイムアウトを処理するときに独自に再試行を行う必要があります。API Gateway は、ダウンストリームの統合に対しては [50 ミリ秒から 29 秒までの統合タイムアウト](https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html#api-gateway-execution-service-limits-table)をサポートしており、統合リクエストがタイムアウトしたときは再試行を行いません。
+  タイムアウト時のリモート呼び出しを回避するには、[サーキットブレーカー](https://martinfowler.com/bliki/CircuitBreaker.html)のパターンを実装します。呼び出しが失敗しないように回線を開き、呼び出しが正常に応答したら回線を閉じます。
+  コンテナベースのワークロードについては、「[App Mesh Envoy](https://docs.aws.amazon.com/app-mesh/latest/userguide/envoy.html)」の機能を確認して、組み込みのタイムアウトとサーキットブレーカーを活用します。
+  AWS Step Functions を使用して、リモートサービスを呼び出すための (特に、ワークロードを簡素化する目的で AWS ネイティブの SDK と、サポートされている Step Functions 統合とを呼び出すための)、ローコードのサーキットブレーカーを作成します。

## リソース
<a name="resources"></a>

 **関連するベストプラクティス:** 
+  [REL05-BP03 再試行呼び出しを制御および制限する](rel_mitigate_interaction_failure_limit_retries.md) 
+  [REL05-BP04 フェイルファストとキューの制限](rel_mitigate_interaction_failure_fail_fast.md) 
+  [REL06-BP07 システムを通じたリクエストのエンドツーエンドのトレースをモニタリングする](rel_monitor_aws_resources_end_to_end.md) 

 **関連ドキュメント:** 
+  [AWS SDK: 再試行とタイムアウト](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/retries-timeouts.html) 
+  [Amazon Builders' Library: ジッターを伴うタイムアウト、再試行、およびバックオフ](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/) 
+ [Amazon API Gateway のクォータと重要な注意点](https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html)
+ [AWS Command Line Interface: コマンドラインオプション](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html)
+ [AWS SDK for Java 2.x: API タイムアウトの設定](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/best-practices.html#bestpractice5)
+ [AWSBotocore using the config object and Config Reference](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html#using-the-config-object)
+ [AWS SDK for .NET: Retries and Timeouts](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/retries-timeouts.html)
+ [AWS Lambda: AWS Lambda 関数の設定](https://docs.aws.amazon.com/lambda/latest/dg/configuration-function-common.html)

 **関連する例:** 
+ [Using the circuit breaker pattern with AWS Step Functions and Amazon DynamoDB](https://aws.amazon.com/blogs/compute/using-the-circuit-breaker-pattern-with-aws-step-functions-and-amazon-dynamodb/)
+ [Martin Fowler: CircuitBreaker](https://martinfowler.com/bliki/CircuitBreaker.html?ref=wellarchitected)

 **関連ツール:** 
+ [AWS SDK](https://docs.aws.amazon.com/index.html#sdks)
+ [AWS Lambda](https://aws.amazon.com/lambda/)
+ [Amazon Simple Queue Service](https://aws.amazon.com/sqs/)
+ [AWS Step Functions](https://aws.amazon.com/step-functions/)
+ [AWS Command Line Interface](https://aws.amazon.com/cli/)