如何解决在使用 AWS SDK 调用 Lambda 函数时出现的重试和超时问题?
当我使用 AWS SDK 调用 AWS Lambda 函数时,该函数超时,API 请求失败或 API 操作重复。
简短描述
由于以下情况,使用 AWS 开发工具包调用 Lambda 函数时可能会出现重试和超时问题:
- 远程 API 无法访问或需要很长时间才能响应 API 调用。
- API 调用在套接字超时时间内没有得到响应。
- 在 Lambda 函数的超时时间内,API 调用没有得到响应。
**注意:**出现网络连接问题时,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 获取有关连接失败以及每次连接尝试重试次数的详细信息。有关详细信息,请参阅将 CloudWatch Logs 日志与 Lambda 结合使用。或者,请参阅您使用的 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
相关信息
相关内容
- AWS 官方已更新 1 个月前
- AWS 官方已更新 2 个月前
- AWS 官方已更新 1 年前