如何對使用 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 呼叫
- 紀錄適用於 .NET 的 AWS SDK
- 紀錄服務呼叫 (適用於 Go 的 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 請求因函數逾時而結束,請嘗試下列其中一個操作:
- 變更 SDK 中的重試設定,以便在逾時內進行所有重試。
- 暫時增加 Lambda 函數逾時設定,以允許足夠的時間產生 SDK 日誌。
變更 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
相關資訊
相關內容
- 已提問 4 個月前lg...
- 已提問 1 個月前lg...
- AWS 官方已更新 2 年前
- AWS 官方已更新 3 個月前