AWS SDK を使用して Lambda 関数を呼び出す際の、再試行とタイムアウトの問題をトラブルシューティングする方法を教えてください。

所要時間4分
0

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 秒
Java310 秒50 秒
.NET4100 秒300 秒
Go3該当なし該当なし

再試行とタイムアウトの問題をトラブルシューティングするには、まず API コールのログを確認して問題を特定します。次に、各ユースケースの必要に応じて AWS SDK の再試行回数とタイムアウト設定を変更します。API コールへの応答に十分な時間を確保するには、Lambda 関数のタイムアウト設定に時間を追加します。

解決策

AWS SDK によって行われた API コールを記録する

Amazon CloudWatch Logs を使用して、失敗した接続の詳細と、それぞれの再試行の試行回数を取得します。詳細については、「Lambda で CloudWatch Logs のログを使用する」を参照してください。または、使用している AWS SDK に関する次の手順を参照してください。

**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 リクエストが終了した場合は、次のいずれかを試してください。

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

関連情報

呼び出し

Lambda での再試行動作について

Lambda のクォータ

コメントはありません

関連するコンテンツ