如何對使用 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 取得有關失敗連線以及每個連線的重試次數的詳細資訊。如需詳細資訊,請參閱存取 AWS Lambda 的 Amazon CloudWatch Logs。或者,請參閱您正在使用的 AWS SDK 的下列指示:

API 呼叫無法建立連線 (連線逾時) 的範例錯誤日誌

START RequestId: b81e56a9-90e0-11e8-bfa8-b9f44c99e76d Version: $LATEST
2018-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: $LATEST
2018-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 或程式碼進行重試

如需有關變更重試計數和逾時設定的詳細資訊,請參閱下列 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

    }

});

用於變更重試計數和逾時設定的範例 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 API 參考)

AWS Lambda 中的錯誤處理和自動重試

Lambda 配額

AWS 官方
AWS 官方已更新 3 年前