如何對使用 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

**注意:**如果 API 請求在 Lambda 函數的逾時內未收到回應,則不會產生這些日誌。如果 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 函數逾時計算

**注意:**下列計算適用於設定為三次重試、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 配額

AWS 官方
AWS 官方已更新 2 個月前