Complete a 3 Question Survey and Earn a re:Post Badge
Help improve AWS Support Official channel in re:Post and share your experience - complete a quick three-question survey to earn a re:Post badge!
AWS SDK を使用して Lambda 関数を呼び出す際の、再試行とタイムアウトの問題をトラブルシューティングする方法を教えてください。
AWS SDK で AWS Lambda 関数を呼び出すと、関数のタイムアウト、API リクエストの失敗、API アクションの重複などの問題が発生します。
簡単な説明
AWS SDK で Lambda 関数を呼び出したときに、次の状態が原因で、再試行とタイムアウトの問題が発生する可能性があります。
- リモート API にアクセスできないか、API コールへの応答に時間がかかりすぎている。
- API コールが、ソケットタイムアウトまでに応答を取得していない。
- API コールが Lambda 関数のタイムアウト期間内に応答を取得していない。
注: ネットワーク接続の問題が発生すると、API コールに想定を超えた時間がかかる場合があります。ネットワークの問題により、再試行や API リクエストの重複が発生する可能性もあります。Lambda 関数がべき等であることを確認し、このような事態に備えてください。
AWS SDK を使用して API コールを行い、呼び出しが失敗した場合、AWS SDK は自動的に呼び出しを再試行します。AWS SDK が再試行する回数と期間は、各 AWS SDK の設定によって左右されます。
デフォルトの AWS SDK 再試行設定
注: 一部の値は、他の AWS サービスでは異なる場合があります。
AWS SDK | 最大再試行回数 | 接続タイムアウト | ソケットタイムアウト |
Python (Boto 3) | サービスにより異なる | 60 秒 | 60 秒 |
JavaScript/Node.js | サービスにより異なる | 該当なし | 120 秒 |
Java | 3 | 10 秒 | 50 秒 |
.NET | 4 | 100 秒 | 300 秒 |
Go | 3 | 該当なし | 該当なし |
再試行とタイムアウトの問題をトラブルシューティングするには、まず API コールのログを確認して問題を特定します。次に、各ユースケースの必要に応じて AWS SDK の再試行回数とタイムアウト設定を変更します。API コールへの応答に十分な時間を確保するには、Lambda 関数のタイムアウト設定に時間を追加します。
解決策
AWS SDK によって行われた API コールを記録する
Amazon CloudWatch Logs を使用して、失敗した接続の詳細と、それぞれの再試行の試行回数を取得します。詳細については、「Lambda で CloudWatch Logs のログを使用する」を参照してください。または、使用している AWS SDK に関する次の手順を参照してください。
- Python Lambda 関数のログ記録と監視
- JavaScript 呼び出しに関する AWS SDK のログ記録
- Java 呼び出しに関する AWS SDK のログ記録
- AWS SDK for .NET によるログ記録
- サービスコールのログ記録 (AWS SDK for Go)
**API コールが接続の確立に失敗したエラーログの例 (接続タイムアウト) **
START RequestId: b81e56a9-90e0-11e8-bfa8-b9f44c99e76d Version: $LATEST2018-07-26T14:32:27.393Z b81e56a9-90e0-11e8-bfa8-b9f44c99e76d [AWS ec2 undefined 40.29s 3 retries] describeInstances({}) 2018-07-26T14:32:27.393Z b81e56a9-90e0-11e8-bfa8-b9f44c99e76d { TimeoutError: Socket timed out without establishing a connection ...
API コールの接続は成功したが、API 応答に時間がかかりすぎたためにタイムアウトしたエラーログの例 (ソケットタイムアウト)
START RequestId: 3c0523f4-9650-11e8-bd98-0df3c5cf9bd8 Version: $LATEST2018-08-02T12:33:18.958Z 3c0523f4-9650-11e8-bd98-0df3c5cf9bd8 [AWS ec2 undefined 30.596s 3 retries] describeInstances({})2018-08-02T12:33:18.978Z 3c0523f4-9650-11e8-bd98-0df3c5cf9bd8 { TimeoutError: Connection timed out after 30s
注: Lambda 関数のタイムアウトまでに API リクエストが応答を取得しなかった場合、これらのログは生成されません。関数のタイムアウトが原因で API リクエストが終了した場合は、次のいずれかを試してください。
- SDK の再試行設定を変更して、すべての再試行がタイムアウトまでに行われるようにします。
- SDK ログを生成するのに十分な時間を確保するために、一時的に Lambda 関数のタイムアウト設定を増やします。
AWS SDK の設定を変更する
AWS SDK の再試行回数とタイムアウトの設定には、API コールが応答を受け取るまでに十分な時間が必要です。各設定の適切な値を決定するには、複数の設定をテストして次の情報を取得します。
- 正常に接続を確立するまでの平均時間
- 完全な API リクエストが正常に返されるまでにかかる平均時間
再試行回数とタイムアウト設定の変更に関する詳細については、次の AWS SDK クライアント設定ドキュメントを参照してください。
各ランタイムの再試行回数とタイムアウト設定を変更するコマンドの例を次に示します。
注: 各設定の例の値は、ユースケースでの値に置き換えてください。
再試行回数とタイムアウト設定を変更する Python (Boto 3) コマンドの例
# max_attempts: retry count / read_timeout: socket timeout / connect_timeout: new connection timeout from botocore.session import Session from botocore.config import Config s = Session() c = s.create_client('s3', config=Config(connect_timeout=5, read_timeout=60, retries={'max_attempts': 2}))
再試行回数とタイムアウト設定を変更する JavaScript/Node.js コマンドの例
// maxRetries: retry count / timeout: socket timeout / connectTimeout: new connection timeout var AWS = require('aws-sdk'); AWS.config.update({ maxRetries: 2, httpOptions: { timeout: 30000, connectTimeout: 5000 } });
再試行回数とタイムアウト設定を変更する JavaScript V3 コマンドの例
const { S3Client, ListBucketsCommand } = require("@aws-sdk/client-s3"); const { NodeHttpHandler } = require("@aws-sdk/node-http-handler"); const client = new S3Client({ requestHandler: new NodeHttpHandler({ connectionTimeout: 30000, socketTimeout: 50000 }), maxAttempts: 2 });
再試行回数とタイムアウト設定を変更する Java コマンドの例
// setMaxErrorRetry(): retry count / setSocketTimeout(): socket timeout / setConnectionTimeout(): new connection timeout ClientConfiguration clientConfig = new ClientConfiguration(); clientConfig.setSocketTimeout(60000); clientConfig.setConnectionTimeout(5000); clientConfig.setMaxErrorRetry(2); AmazonDynamoDBClient ddb = new AmazonDynamoDBClient(credentialsProvider,clientConfig);
再試行回数とタイムアウト設定を変更する.NET コマンドの例
// MaxErrorRetry: retry count / ReadWriteTimeout: socket timeout / Timeout: new connection timeout var client = new AmazonS3Client( new AmazonS3Config { Timeout = TimeSpan.FromSeconds(5), ReadWriteTimeout = TimeSpan.FromSeconds(60), MaxErrorRetry = 2 });
**再試行回数設定を変更する Go コマンドの例 **
// Create Session with MaxRetry configuration to be shared by multiple service clients.sess := session.Must(session.NewSession(&aws.Config{ MaxRetries: aws.Int(3), })) // Create S3 service client with a specific Region. svc := s3.New(sess, &aws.Config{ Region: aws.String("us-west-2"), })
リクエストのタイムアウト設定を変更する Go コマンドの例
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)defer cancel() // SQS ReceiveMessage params := &sqs.ReceiveMessageInput{ ... } req, resp := s.ReceiveMessageRequest(params) req.HTTPRequest = req.HTTPRequest.WithContext(ctx) err := req.Send()
(オプション) Lambda 関数のタイムアウト設定を変更する
Lambda 関数のタイムアウト時間が短いと、正常な接続が早期に切断される可能性があります。API コールが応答を得るのに十分な時間を確保するために、関数のタイムアウト設定を増やしてください。
次の式を使用して、関数のタイムアウトに必要な基準時間を推定します。
First attempt (connection timeout + socket timeout) + Number of retries x (connection timeout + socket timeout) + 20 seconds additional code runtime margin = Required Lambda function timeout
Lambda 関数のタイムアウト計算例
注: 次の計算は、3 回の再試行、10 秒の接続タイムアウト、30 秒のソケットタイムアウトで設定された AWS SDK を対象としています。
First attempt (10 seconds + 30 seconds) + Number of retries [3 * (10 seconds + 30 seconds)] + 20 seconds additional code runtime margin = 180 seconds