AWS Lambda 深入解析与应用实践
1. Lambda 启动延迟与语言差异
不同编程语言编写的 Lambda 函数启动延迟存在差异,可达几百毫秒。较大且代码较多的微服务会加大这种差异。在 Lambda 支持的编程语言中,JavaScript 和 Python 的启动延迟差异最小,Java 和 C# 最大。通常,分配的内存量对启动延迟影响不大,但对于 C# 微服务,内存分配会产生显著影响,建议至少分配 2GB 内存。
2. 预留并发
Lambda 并发限制在账户和区域内的所有 Lambda 函数间共享。达到限制后,Lambda 调用会被限流,用户需等待并发空间释放。我们可给特定的 Lambda 微服务分配预留并发,防止其被限流。未分配的并发空间称为未预留并发,供所有无预留并发的 Lambda 微服务共享。
预留并发也是一种限制器,将函数可运行的实例数量限制为预留的数量。例如,若预留并发设为 10,无论有无可用的未预留并发,该微服务任何时候最多只能执行 10 个实例。达到预留并发上限时,额外请求会被限流,用户需等待。
| 并发类型 | 说明 |
|---|---|
| 预留并发 | 为特定 Lambda 微服务分配,防止限流,限制实例运行数量 |
| 未预留并发 | 供无预留并发的 Lambda 微服务共享 |
3. Lambda 层
Lambda 层可将代码从微服务中分离,同时保持交互。层可包含库、自定义运行时、数据或配置文件,附加到微服务的层会计入 250MB 的最大代码大小限制。
依赖 Lambda 层在多个函数间共享通用实用函数是一种反模式。虽可减少代码重复,但因共享代码会使微服务架构变成单体架构,层的未来更改可能破坏依赖它的一个或多个微服务。
Lambda 层的一个好用途是将第三方代码从单个微服务中分离。例如,将第三方图像处理库放在一个层中,负责创建缩略图的微服务是唯一包含该层的服务,这样可缩小微服务代码库,分离第三方代码,且不会在多个微服务间创建依赖。
4. 是否使用 VPC
Lambda 作为完全托管的 AWS 服务运行,默认情况下,微服务在 AWS 管理的 VPC 中运行,访问权限和安全性通过 IAM 角色策略完全管理。
在大型企业中,常要求 Lambda 微服务在企业管理的 VPC 中运行,通常与要求子网隔离的安全策略有关。但将 Lambda 添加到 VPC 会增加额外复杂性,包括稍高的冷启动延迟、需配置和管理安全组,可能还需要代理或 NAT,而这两者都不属于无服务器范畴。
AWS 建议采用纵深防御,即包括子网隔离在内的多层安全保护。最终,是否值得增加这种复杂性取决于具体用例和组织要求。
graph LR
A[是否使用 VPC] -->|是| B(增加复杂性)
A -->|否| C(使用 AWS 管理 VPC)
B --> D(稍高冷启动延迟)
B --> E(配置管理安全组)
B --> F(可能需代理或 NAT)
5. Lambda Hyperplane 架构
以前,每个 Lambda 函数实例都需创建一个 ENI,存在诸多挑战。例如,可配置的 Lambda 数量受 VPC 支持的 ENI 数量和配置范围内可用 IP 地址数量限制,且冷启动时间较长,因为每个实例在可用前都需附加到一个 ENI。
新的 Hyperplane 方法允许将多个微服务实例附加到一个 Hyperplane,可大幅减少冷启动时间,因为能快速创建隧道以建立与 VPC 的连接。同时,由于 ENI 数量大幅减少,我们不太可能耗尽它们,也无需担心管理 IP 地址池。
首次在 VPC 中创建或更新 Lambda 微服务时,Hyperplane 的初始设置可能需长达 90 秒。设置完成后,Hyperplane 保持可用,随时可启动该微服务的未来实例。但如果 Lambda 微服务数周未使用,Hyperplane 可能会被停用。对于使用较少的微服务,可使用 EventBridge 安排每周调用以避免此问题。
6. Lambda DevOps
Lambda 与 AWS 原生部署服务(如 CodePipeline)集成,可快速测试、构建和部署新的微服务版本。应使用 CloudFormation 或其他基础设施即代码(IaC)模板语言来配置 Lambda 微服务以及任何集成和权限。
有几种部署技术可供选择,对无服务器架构(尤其是 Lambda 微服务)最相关的是蓝绿部署和金丝雀部署:
-
蓝绿部署
:在全新的绿色环境中完全部署应用程序的新版本。开发人员测试新功能后,将流量从旧的蓝色环境路由到新的绿色环境。若绿色环境出现问题,可迅速将流量移回蓝色环境。但蓝绿部署的风险在于会一次性转移 100% 的流量,出现问题时可能影响所有用户。
-
金丝雀部署
:类似于蓝绿部署,但不是一次性转移所有流量,而是先将一小部分可配置的流量转移到新环境。若没有问题,再将剩余流量一次性或分阶段转移。与蓝绿部署一样,若新部署出现问题,可将已转移的流量移回旧环境,这可通过对 CloudWatch 事件错误日志做出反应来完全自动化。金丝雀部署可减少可能受问题影响的用户数量,最小化处于错误状态的时间。
graph LR
A[蓝绿部署] --> B(在新环境部署新版本)
B --> C(测试新功能)
C --> D(转移流量到新环境)
D -->|有问题| E(移回流量到旧环境)
F[金丝雀部署] --> G(转移小部分流量到新环境)
G -->|无问题| H(转移剩余流量)
G -->|有问题| I(移回已转移流量)
7. Lambda 环境变量
Lambda 支持使用环境变量存储信息,如 SQS URL 或 S3 存储桶名称。但将敏感数据存储在环境变量中并非最佳实践,尽管 Lambda 环境变量在静止时加密,但有权限在 AWS 控制台或 CLI 中查看 Lambda 微服务的人仍可看到这些变量。
为遵循最小权限原则(PoLP),最佳做法是将 Lambda 访问与敏感信息访问分离。对于密码和其他凭证等信息,可使用免费的系统管理器参数存储服务,将值类型设为“安全字符串”,这样可完全加密存储敏感数据,并通过 IAM 策略为用户或服务管理对数据的细粒度访问。另一个名为 Secrets Manager 的服务也提供相同功能,它是更高级的服务,具有自动密码轮换等功能,但该服务不是免费的,每个存储的机密需按月计费。
8. Lambda 与 CloudWatch
要开始为 Lambda 使用 CloudWatch,第一步是授予 Lambda 访问 CloudWatch 日志的权限。在 CloudWatch 中,日志按组组织,可区分不同服务、应用程序和微服务的日志。
创建日志组后,Lambda 微服务需要有向其写入日志的权限。若我们创建特定的日志组,只需给 Lambda 两个权限:
logs:CreateLogStream
和
logs:PutLogEvents
,此方法还可配置日志的保留设置。若不事先创建日志组,希望 Lambda 在首次执行时自动创建,微服务还需要
logs:CreateLogGroup
权限,但要注意,为遵循 PoLP,微服务仅在首次运行或日志组被删除时才需要此权限。
9. CloudWatch 监控指标
除之前详细介绍的内存指标外,还有以下关键 Lambda 指标值得关注:
-
并发限制
:可以是并发执行数,也可以是并发执行数和未预留并发执行数的组合,取决于部分函数是否有预留并发。此区域范围的指标决定 Lambda 微服务是否即将开始限流请求,对于有大量并发事件的系统,跟踪该指标很重要。
-
错误(标准 Lambda 失败错误)
:Lambda 微服务中的错误若属于工作流的一部分,可能会给其他微服务带来问题。应配置警报,通知应用程序团队此类事件,以便快速跟进。注意,此类错误是否出现取决于代码,若我们认真处理错误(如使用
try/catch
),可输出自己的、可能更有意义的错误消息和状态代码,这些标准的 Lambda 通用错误可能不会出现。
-
死信错误
:该指标与数据丢失有关,当失败的事件无法写入安全的备份位置以进行调试和重新运行时会出现。建议配置警报,以便团队立即解决问题。
-
持续时间
:Lambda 微服务应小巧快速,跟踪执行持续时间很重要,当达到不可接受的阈值时应设置警报,这有助于团队调试并找出导致性能下降和成本增加的边缘情况的原因。
| 指标名称 | 说明 | 重要性 |
|---|---|---|
| 并发限制 | 决定 Lambda 微服务是否限流请求 | 对多并发事件系统重要 |
| 错误 | 可能影响工作流中的其他微服务 | 需配置警报跟进 |
| 死信错误 | 与数据丢失有关 | 需配置警报解决问题 |
| 持续时间 | 跟踪微服务执行速度 | 有助于调试和控制成本 |
10. Lambda 与 API Gateway
API Gateway 是与 Lambda 最常用的服务之一,尤其在面向用户的解决方案中。它是应用程序访问微服务的前门,可管理、监控和保护对 API 的访问。API Gateway 是完全托管的云服务,无需代码开发,开发人员可利用无服务器功能提高生产力,降低运营成本。
API Gateway 支持三种类型的接口:
-
WebSocket API
:用于后端和前端之间的实时双向通信,常用于聊天应用和游戏,在无服务器架构中,可在异步请求完成时让后端更新前端。WebSocket 连接保持打开状态,无需为每个请求发起新连接。
-
HTTP API
:创建 RESTful API,更简单,延迟和成本更低,虽名为 HTTP API,但连接仍通过 HTTPS 进行 SSL 加密。
-
REST API
:也是创建 RESTful API,提供更多功能,如使用计划、缓存和防火墙集成,最重要的是支持数据验证,可避免在微服务中进行数据验证,建议除最简单的 API 外都使用此类型。此外,还可直接使用该服务和 Lambda 提供动态 HTML 页面。
11. WebSockets
HTTP 协议在某些情况下并非理想选择,特别是对于需要处理数据流或后端需主动向前端推送数据的应用程序。2011 年,WebSocket 协议标准化,解决了这些需求。与 HTTP 不同,WebSocket 连接到服务器后保持打开状态,直到客户端或服务器发出终止请求,可在后端需要时将数据推送到浏览器,而无需前端主动请求。
使用 API Gateway WebSockets,可在 Web 客户端和 API 之间创建开放连接。API Gateway 与客户端保持开放连接,并将单个请求传递给微服务。重要的是,每个请求都会启动 Lambda 微服务,且微服务在请求之间无需保持运行。
以下是使用 Lambda 设置 WebSockets 的步骤:
1. 使用 CDK 的
apigatewayv2
模块创建一个新的 API,协议类型为
WEBSOCKET
。
2. 创建一个角色,允许 API 对处理套接字的微服务有
lambda:invokefunction
访问权限(先创建 Lambda 微服务)。
3. 使用
CfnIntegration
添加 Lambda 集成,分别为
$connect
、
$disconnect
和
$default
(或
$message
)添加集成,对于 WebSockets,集成类型始终为代理。
4. 使用
CfnRoute
创建三条路由,分别为
$connect
、
$disconnect
和
$default
,目标是步骤 3 中创建的集成。
5. 最后,创建部署(
CfnDeployment
)和阶段(
CfnStage
),使用
ConcreteDependable
确保三条路由是部署的依赖项,以保证资源按正确顺序加载。
API Gateway 服务会提供一个
wss://
URL 用于连接 WebSocket,我们可用纯 JavaScript 连接:
// connect
const mySocket = new WebSocket(api_socket_url);
// listen for incoming messages
mySocket.onmessage = function(message) {
// handle message
}
// send a message
app.socket.send(message);
Lambda 微服务处理套接字的代码如下:
// connect, disconnect or default
let action = event.requestContext.routeKey;
// this client’s ID
let cid = event.requestContext.connectionId;
// new connection
if(action === '$connect') {
// optionally store the session in a DDB
}
// new incoming request
if(action === '$default') {
// handle the requests
}
// send a message to the client
const apigwManagementApi = new AWS.ApiGatewayManagementApi({
apiVersion: '2018-11-29',
// retrieve from API GW, the link that starts with https://
endpoint: <SOCKET_URL_FOR_MESSAGES>
});
apigwManagementApi.postToConnection({
ConnectionId: <RECIPIENT_CLIENT_ID>,
Data: <MESSAGE>
}).promise();
12. 代理与非代理集成
API Gateway REST API 与 Lambda 提供两种集成类型:代理集成和非代理集成。
-
代理集成
:所有请求和响应原封不动地转发到目标 Lambda,使用代理集成会失去 API Gateway 的许多强大功能,但在以下两种情况下不可避免:
- Lambda 中运行的第三方服务库期望接收完整未修改的 API 请求,如 PayPal 等敏感服务。
- 服务器库,如可在 Lambda 中运行的 GraphQL API Apollo。
-
非代理集成
:可利用 API Gateway 功能分析、验证和转换请求和响应的内容,这是无服务器架构的推荐方法,可将有效负载和 HTTP 状态信息与应用程序逻辑解耦,还能对用户输入进行参数验证,避免在 Lambda 中重复操作并节省成本。
| 集成类型 | 说明 | 适用场景 |
|---|---|---|
| 代理集成 | 原封不动转发请求和响应 | 第三方服务库、特定服务器库 |
| 非代理集成 | 可分析、验证和转换内容 | 无服务器架构推荐 |
13. 请求转换
API Gateway 的另一个有用功能是请求转换,可对请求头进行转换等操作。
14. 动态 HTML
Lambda 微服务通常用于处理后端事件和 API 端点,但也可直接返回带有动态内容的 HTML 标记。配置 API Gateway 将其传递给用户,可实现动态网站而非基于 API 的网站,这是实现对 SEO 友好的动态页面的一种方法,但延迟较大。
15. 错误报告
API Gateway 的错误报告功能不佳,可通过以下两个技巧稍作改进:
1. 在 API Gateway “网关响应”的标准 400 和 500 响应中添加以下头:
Access-Control-Allow-Origin: '*'
,确保客户端能接收错误响应,避免因 CORS 问题失败。
2. 在“网关响应”错误类型“BAD_REQUEST_BODY”的“application/json”请求体中添加以下代码:
,"error":"$context.error.validationErrorString"
,可在标准错误代码基础上提供更多信息,有助于查找问题,但仍需一些试错才能确定确切原因。
16. 其他集成
除 Lambda 外,API Gateway 还可与其他多个可处理传入请求并提供响应的服务集成,如 ECS 和 Fargate 容器,以及直接与 EC2 服务器集成。还可直接与一些 AWS 服务 API 集成,例如,用户只需打开一个 URL 就能启动 Step Functions 工作流,而无需采用与 Step Functions API 直接交互的复杂方法。
17. 总结与最佳实践
17.1 Lambda 性能优化
- 语言选择 :考虑到启动延迟差异,对于对启动速度要求高的场景,优先选择 JavaScript 或 Python。若使用 C#,确保分配至少 2GB 内存。
- 并发管理 :合理分配预留并发,避免因并发限制导致的限流问题。对于高并发场景,提前规划并发策略。
- 层的使用 :避免使用 Lambda 层共享通用实用函数,而是将其用于分离第三方代码,保持微服务的独立性。
- VPC 使用 :权衡使用 VPC 的利弊,只有在确实有安全需求时才将 Lambda 微服务部署到企业管理的 VPC 中。若使用,可采用 Hyperplane 架构减少冷启动延迟。
17.2 部署策略选择
- 蓝绿部署 :适用于对新功能有充分信心,且希望快速切换到新版本的场景,但要做好回滚准备。
- 金丝雀部署 :更适合对风险较为敏感的场景,可逐步验证新版本的稳定性,减少问题影响范围。
17.3 监控与错误处理
- 监控指标 :密切关注并发限制、错误、死信错误和持续时间等关键指标,及时发现并解决潜在问题。
- 错误报告 :按照前文提到的技巧改进 API Gateway 的错误报告,提高问题排查效率。
17.4 集成与功能使用
- API Gateway 集成 :根据不同的业务需求选择合适的 API Gateway 接口类型。对于实时双向通信,使用 WebSocket API;对于简单的 RESTful API,可选择 HTTP API;对于需要更多功能和数据验证的场景,优先使用 REST API。
- 请求转换和动态 HTML :合理利用 API Gateway 的请求转换功能,以及 Lambda 微服务返回动态 HTML 的能力,实现更灵活的应用。
graph LR
A[性能优化] --> B(语言选择)
A --> C(并发管理)
A --> D(层的使用)
A --> E(VPC 使用)
F[部署策略] --> G(蓝绿部署)
F --> H(金丝雀部署)
I[监控与错误处理] --> J(监控指标)
I --> K(错误报告)
L[集成与功能使用] --> M(API Gateway 集成)
L --> N(请求转换和动态 HTML)
18. 实际案例分析
18.1 电商订单处理系统
某电商平台的订单处理系统使用 Lambda 微服务和 API Gateway 构建。系统采用了以下架构和策略:
-
API Gateway 选择
:使用 REST API 处理订单创建、查询等操作,利用其数据验证功能确保订单数据的准确性。
-
并发管理
:为订单处理的 Lambda 微服务分配了适当的预留并发,以应对高峰时段的大量订单请求。
-
监控指标
:监控并发限制、错误和持续时间等指标,及时发现并解决了一些因代码问题导致的错误和性能瓶颈。
-
部署策略
:采用金丝雀部署方式更新系统功能,先将小部分流量导向新版本,验证无误后再逐步扩大范围,确保了系统的稳定性。
18.2 实时聊天应用
一个实时聊天应用使用了 WebSocket API 和 Lambda 微服务实现消息的实时收发。具体实现如下:
-
WebSocket 连接
:通过 API Gateway WebSockets 建立客户端和后端的实时连接,确保消息的即时传递。
-
Lambda 处理
:每个消息请求都会触发 Lambda 微服务进行处理,处理完成后将消息返回给客户端。
-
错误处理
:配置了 CloudWatch 警报,当出现死信错误时及时通知开发团队,保证数据的完整性。
| 案例名称 | 系统类型 | 采用技术 | 取得效果 |
|---|---|---|---|
| 电商订单处理系统 | 业务处理系统 | REST API、预留并发、金丝雀部署 | 提高订单处理效率,减少错误率 |
| 实时聊天应用 | 实时通信应用 | WebSocket API、Lambda 微服务 | 实现消息实时收发,保障数据完整 |
19. 未来发展趋势
19.1 更智能的资源管理
随着技术的发展,AWS Lambda 可能会提供更智能的资源管理功能,自动根据业务负载调整内存分配和并发数量,进一步提高资源利用率。
19.2 增强的安全防护
在安全方面,可能会引入更多的自动化安全机制,如实时漏洞检测和自动修复,保障 Lambda 微服务的安全运行。
19.3 与更多服务的深度集成
未来,Lambda 可能会与更多的 AWS 服务以及第三方服务进行深度集成,提供更丰富的功能和更便捷的开发体验。
19.4 对新兴技术的支持
随着新兴技术(如人工智能、机器学习)的发展,Lambda 可能会提供对这些技术的更好支持,帮助开发者更轻松地构建智能应用。
graph LR
A[未来发展趋势] --> B(更智能的资源管理)
A --> C(增强的安全防护)
A --> D(与更多服务的深度集成)
A --> E(对新兴技术的支持)
20. 结语
AWS Lambda 作为一种强大的无服务器计算服务,为开发者提供了高效、灵活的开发方式。通过深入了解 Lambda 的各项特性,如启动延迟、并发管理、层的使用、部署策略、监控指标等,以及与 API Gateway 的集成方式,开发者可以构建出高性能、高可靠性的应用系统。同时,关注未来的发展趋势,不断学习和应用新的技术,将有助于在不断变化的技术环境中保持竞争力。希望本文能为广大开发者在使用 AWS Lambda 时提供有价值的参考和指导。
超级会员免费看
87

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



