Lambda错误处理与扩展的全面解析
1. Lambda错误处理概述
Lambda根据触发调用的事件源来处理错误,事件源主要分为以下几类:
| 事件源类型 | 示例 |
| — | — |
| 同步事件源 | API Gateway |
| 异步事件源 | S3、SNS |
| 流/队列事件源 | Kinesis Data Streams、SQS |
不同类型的事件源处理Lambda函数抛出的错误的模式不同,具体如下:
1.1 同步事件源
这是最简单的模式。对于以这种方式调用的Lambda函数,错误会向上传播回调用者,并且不会自动重试。错误如何暴露给上游客户端取决于Lambda函数的调用方式,因此建议在代码中强制出错,以了解问题是如何暴露的。例如,如果API Gateway是事件源,Lambda函数抛出的错误会导致错误信息被发送回API Gateway,API Gateway会向原始请求者返回500 HTTP响应。
1.2 异步事件源
由于这种调用模式是异步的,没有上游调用者可以对错误进行有效处理,因此Lambda有更复杂的错误处理模型。默认情况下,如果检测到错误,Lambda会再重试处理事件最多两次(总共三次尝试),重试之间会有延迟。如果所有重试尝试都失败,事件将被发送到函数的错误目标和/或死信队列(如果已配置);否则,事件将被丢弃。
1.3 流/队列事件源
如果没有配置错误处理策略,当处理流/队列事件源中的事件时,错误冒泡到Lambda运行时,Lambda会一直重试该事件,直到(a)失败的事件在 upstream source 中过期或(b)问题得到解决。这意味着在错误解决之前,流或队列的处理实际上会被阻塞。
2. 异步事件源错误处理示例
2.1 重试机制
以下是一个示例代码,模拟处理S3事件时抛出错误:
package book;
import com.amazonaws.services.lambda.runtime.events.S3Event;
public class S3ErroringLambda {
public void handler(S3Event event) {
System.out.println("Received new S3 event");
throw new RuntimeException("This function unable to process S3 Events");
}
}
将此函数连接到S3存储桶后,上传文件到该存储桶,会发现Lambda会尝试处理S3事件三次。可以使用单独的CloudFormation资源配置重试次数,例如:
SingleEventInvokeConfig:
Type: AWS::Lambda::EventInvokeConfig
Properties:
FunctionName: !Ref SingleEventLambda
Qualifier: "$LATEST"
MaximumRetryAttempts: 0
2.2 死信队列(DLQ)
Lambda可以将所有重试失败的异步事件源事件自动转发到死信队列(DLQ),DLQ可以是SNS主题或SQS队列。以下是一个包含DLQ和DLQ监听器的SAM模板示例:
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: chapter8-s3-errors
Resources:
DLQ:
Type: AWS::SNS::Topic
ErrorTriggeringBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${AWS::AccountId}-${AWS::Region}-errortrigger
S3ErroringLambda:
Type: AWS::Serverless::Function
Properties:
Runtime: java8
MemorySize: 512
Handler: book.S3ErroringLambda::handler
CodeUri: target/lambda.zip
DeadLetterQueue:
Type: SNS
TargetArn: !Ref DLQ
Events:
S3Event:
Type: S3
Properties:
Bucket: !Ref ErrorTriggeringBucket
Events: s3:ObjectCreated:*
DLQProcessingLambda:
Type: AWS::Serverless::Function
Properties:
Runtime: java8
MemorySize: 512
Handler: book.DLQProcessingLambda::handler
CodeUri: target/lambda.zip
Events:
SnsEvent:
Type: SNS
Properties:
Topic: !Ref DLQ
DLQ处理函数的代码如下:
package book;
import com.amazonaws.services.lambda.runtime.events.SNSEvent;
public class DLQProcessingLambda {
public void handler(SNSEvent event) {
event.getRecords().forEach(snsRecord ->
System.out.println("Received DLQ event: " + snsRecord.toString())
);
}
}
2.3 目标(Destinations)
2019年底,AWS引入了目标(Destinations)作为捕获失败事件的替代方案。Destinations比DLQ更强大,可以捕获错误和成功处理的异步事件,并且支持更多类型的目标,如另一个Lambda函数或EventBridge。以下是一个配置目标的示例:
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: chapter8-s3-errors
Resources:
ErrorTriggeringBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${AWS::AccountId}-${AWS::Region}-errortrigger
S3ErroringLambda:
Type: AWS::Serverless::Function
Properties:
Runtime: java8
MemorySize: 512
Handler: book.S3ErroringLambda::handler
CodeUri: target/lambda.zip
Events:
S3Event:
Type: S3
Properties:
Bucket: !Ref ErrorTriggeringBucket
Events: s3:ObjectCreated:*
Policies:
- LambdaInvokePolicy:
FunctionName: !Ref ErrorProcessingLambda
ErrorProcessingLambda:
Type: AWS::Serverless::Function
Properties:
Runtime: java8
MemorySize: 512
Handler: book.ErrorProcessingLambda::handler
CodeUri: target/lambda.zip
S3ErroringLambdaInvokeConfig:
Type: AWS::Lambda::EventInvokeConfig
Properties:
FunctionName: !Ref S3ErroringLambda
Qualifier: "$LATEST"
DestinationConfig:
OnFailure:
Destination: !GetAtt ErrorProcessingLambda.Arn
3. Kinesis和DynamoDB流错误处理
2019年底,AWS为Kinesis和DynamoDB流事件源添加了一些失败处理功能,以避免“毒丸”场景。这些功能可以通过SAM(或CloudFormation)进行配置,应用于Lambda函数无法处理Kinesis或DynamoDB流中的一批记录时。新功能如下:
3.1 函数错误时二分处理
当Lambda调用失败时,该功能会将记录批次分成两部分,分别重试较小的批次,从而自动将失败范围缩小到导致问题的单个记录。
3.2 最大记录年龄
指示Lambda函数跳过超过指定最大记录年龄(60秒到7天)的记录。
3.3 最大重试次数
对失败的批次进行可配置次数的重试,然后将批次信息发送到配置的失败目标。
3.4 失败时的目标
这是一个SNS主题或SQS队列,将接收有关失败批次的信息,但不接收实际失败的记录。
4. 使用X-Ray跟踪错误
如果使用AWS X-Ray,可以在组件图中显示错误发生的位置,更多详细信息可参考相关文档。
5. 错误处理策略
根据事件源类型和错误类型,选择不同的错误处理策略:
5.1 未处理错误
设置监控,错误发生时可能需要手动干预,紧急程度取决于上下文和事件源类型。
5.2 已处理错误
- 同步事件源:通常希望向原始调用者返回某种错误,建议在Lambda代码中显式返回格式良好的错误,但需要手动跟踪错误指标。
- 异步事件源:是否使用DLQ或Destinations会影响处理方式。如果使用,可以让错误冒泡或抛出自定义错误,在DLQ/Destination处理消息时处理错误;如果不使用,建议在代码中记录失败的输入事件。
- 流/队列事件源:使用上述失败处理功能可以在某些记录导致错误时继续处理,但前提是应用程序可以安全地处理乱序记录。否则,可依赖平台的自动重试行为。
- SQS:建议在代码中处理错误,可在处理函数中添加顶级try-catch块,设置自己的重试策略或记录失败事件并干净地退出函数。
6. Lambda扩展
6.1 自动扩展机制
Lambda具有强大的自动扩展能力。当新事件发生时,如果当前所有函数实例都在使用中,Lambda会自动创建新实例来处理新事件。一段时间不活动后,函数实例会被回收。从成本角度看,Lambda只在函数处理事件时收费,串行处理一百个事件和并行处理一百个事件的成本相同(受冷启动额外时间成本影响)。
6.2 观察Lambda扩展
以下是一个示例代码,用于观察Lambda扩展行为:
package book;
public class MyLambda {
private static final String instanceID =
java.util.UUID.randomUUID().toString();
public String handler(String input) {
return "This is function instance " + instanceID;
}
}
如果连续调用该代码五次,
instanceID
成员的值将始终相同。添加睡眠语句后:
package book;
public class MyLambda {
private static final String instanceID =
java.util.UUID.randomUUID().toString();
public String handler(String input) throws Exception {
Thread.sleep(5000);
return "This is function instance " + instanceID;
}
}
并行调用该函数多次,会发现不同调用返回不同的容器ID,这是因为Lambda会自动扩展以处理更多请求。
6.3 扩展限制和节流
AWS的资源是有限的,Lambda的扩展也有上限。每个AWS账户、每个区域的所有函数的并发执行数量有默认限制(目前为1000),可以申请提高该限制。达到限制时会出现节流,可通过CloudWatch指标监控。不同类型的事件源在节流时的行为不同:
| 事件源类型 | 节流行为 |
| — | — |
| 同步事件源 | 节流被视为错误,以HTTP状态码500错误返回给调用者 |
| 异步事件源 | 默认情况下,Lambda会在最多6小时内重试调用Lambda函数,可通过配置修改 |
| 流/队列事件源 | Lambda会阻塞并重试,直到成功或数据过期 |
此外,还有突发限制,默认情况下Lambda每分钟最多可扩展500个实例,可根据需要请求提高该限制。Lambda还提供了保留并发配置工具,用于解决某个函数扩展过宽影响其他函数的问题。
综上所述,Lambda在错误处理和扩展方面提供了丰富的功能和灵活的配置选项,开发者可以根据具体需求选择合适的策略和设置。
graph LR
A[事件源] -->|同步| B(同步事件源处理)
A -->|异步| C(异步事件源处理)
A -->|流/队列| D(流/队列事件源处理)
B --> E(错误返回给调用者)
C --> F(重试机制)
F -->|失败| G(死信队列/目标)
D --> H(持续重试)
H -->|问题解决| I(继续处理)
H -->|记录过期| J(停止重试)
7. 保留并发配置
保留并发配置是 Lambda 提供的一个重要工具,用于解决某个函数扩展过宽影响其他函数的问题。设置保留并发值有以下两个作用:
-
限制函数的并发执行数量
:确保该函数不会无限制地扩展,从而占用过多的并发资源。
-
保障函数的稳定运行
:即使其他函数扩展过宽,该函数仍能获得一定数量的并发资源,保证其正常运行。
以下是一个设置保留并发的 CloudFormation 资源示例:
MyFunctionReservedConcurrency:
Type: AWS::Lambda::Function
Properties:
FunctionName: MyFunction
Code:
S3Bucket: my-bucket
S3Key: my-function-code.zip
Handler: index.handler
Runtime: nodejs14.x
ReservedConcurrentExecutions: 100
在上述示例中,
ReservedConcurrentExecutions
属性设置为 100,表示为
MyFunction
函数保留 100 个并发执行资源。
8. 扩展策略选择
在实际应用中,需要根据不同的业务场景和需求选择合适的扩展策略:
8.1 高并发场景
如果业务需要处理大量的并发请求,例如电商平台的促销活动期间,建议提高 Lambda 的并发限制,并合理设置保留并发,以确保系统能够稳定运行。同时,可以使用异步事件源和流/队列事件源,利用 Lambda 的自动扩展能力并行处理大量事件。
8.2 低并发场景
对于低并发的业务场景,如内部管理系统,默认的并发限制通常已经足够。可以通过监控系统性能,根据实际情况进行微调,避免资源浪费。
8.3 弹性扩展场景
对于业务流量波动较大的场景,如社交媒体平台的热门话题讨论期间,可以使用 Lambda 的自动扩展能力,结合 CloudWatch 监控和自动伸缩策略,根据实际流量动态调整函数的并发执行数量。
9. 综合应用示例
以下是一个综合应用 Lambda 错误处理和扩展的示例,假设我们有一个处理用户上传文件的系统,使用 S3 作为存储,Lambda 函数处理文件上传事件:
9.1 架构设计
graph LR
A[用户上传文件] --> B(S3 存储桶)
B --> C(Lambda 函数处理)
C -->|成功| D(后续处理)
C -->|失败| E(死信队列)
E --> F(错误处理 Lambda 函数)
F --> G(存储错误信息到 S3)
9.2 代码实现
处理文件上传的 Lambda 函数
package book;
import com.amazonaws.services.lambda.runtime.events.S3Event;
public class FileProcessingLambda {
public void handler(S3Event event) {
try {
// 处理文件上传逻辑
System.out.println("Processing file from S3 event");
} catch (Exception e) {
throw new RuntimeException("Failed to process file", e);
}
}
}
错误处理 Lambda 函数
package book;
import com.amazonaws.services.lambda.runtime.events.SNSEvent;
public class ErrorProcessingLambda {
public void handler(SNSEvent event) {
event.getRecords().forEach(snsRecord ->
System.out.println("Received DLQ event: " + snsRecord.toString())
);
// 将错误信息存储到 S3
// 具体实现省略
}
}
SAM 模板配置
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: File processing system
Resources:
DLQ:
Type: AWS::SNS::Topic
FileUploadBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: my-file-upload-bucket
FileProcessingLambda:
Type: AWS::Serverless::Function
Properties:
Runtime: java8
MemorySize: 512
Handler: book.FileProcessingLambda::handler
CodeUri: target/lambda.zip
DeadLetterQueue:
Type: SNS
TargetArn: !Ref DLQ
Events:
S3Event:
Type: S3
Properties:
Bucket: !Ref FileUploadBucket
Events: s3:ObjectCreated:*
ErrorProcessingLambda:
Type: AWS::Serverless::Function
Properties:
Runtime: java8
MemorySize: 512
Handler: book.ErrorProcessingLambda::handler
CodeUri: target/lambda.zip
Events:
SnsEvent:
Type: SNS
Properties:
Topic: !Ref DLQ
9.3 错误处理和扩展策略
-
错误处理
:当
FileProcessingLambda函数处理文件失败时,错误事件会被发送到死信队列(DLQ),由ErrorProcessingLambda函数进行处理,将错误信息存储到 S3 中,方便后续分析。 - 扩展策略 :根据实际业务流量,调整 Lambda 的并发限制和保留并发,确保系统能够处理大量的文件上传请求。同时,使用 Lambda 的自动扩展能力,根据请求数量动态调整函数的实例数量。
10. 总结
Lambda 在错误处理和扩展方面提供了丰富的功能和灵活的配置选项,开发者可以根据不同的事件源类型和业务需求,选择合适的错误处理策略和扩展策略。以下是一些关键要点总结:
| 要点 | 说明 |
| — | — |
|
错误处理
| 根据事件源类型(同步、异步、流/队列)采用不同的错误处理方式,如重试机制、死信队列、目标等。 |
|
扩展策略
| 利用 Lambda 的自动扩展能力,结合并发限制、突发限制和保留并发配置,根据业务流量动态调整函数的并发执行数量。 |
|
综合应用
| 在实际项目中,综合考虑错误处理和扩展策略,设计合理的架构,确保系统的稳定性和可靠性。 |
通过合理运用这些功能,开发者可以构建出高效、稳定、可扩展的无服务器应用程序。在实际开发过程中,还需要不断监控系统性能,根据实际情况进行调整和优化,以满足不断变化的业务需求。
超级会员免费看
454

被折叠的 条评论
为什么被折叠?



