2. AWS Lambda深入
上一节我们从整体上认识了 Serverless 与 Lambda 的定位。这一节要把 Lambda 拆开来看:一个函数从创建到稳定运行,背后涉及配置、运行时、层、内存与超时、并发模型以及冷启动这几条相互牵连的主线。理解它们之间的耦合关系,比单独记住某个参数更重要。
函数创建与配置:把“代码 + 配置”绑定成一个可调用单元
创建一个 Lambda 函数,本质上是把一段代码与一组运行配置绑定成一个可调用单元。核心配置项包括:函数名、运行时(Runtime)、执行角色(Execution Role)、处理程序入口(Handler)、代码来源(内联编辑、ZIP 上传或 S3 引用)、内存大小、超时时间、环境变量、层、VPC 设置以及并发控制。其中执行角色决定了函数能访问哪些 AWS 资源,例如写 CloudWatch Logs、读写 DynamoDB 或访问 S3,这是最容易被忽视却最常导致“函数能跑但一调用就报 AccessDenied”的地方。
处理程序的命名遵循“文件名.函数名”的约定,例如 Node.js 中 index.handler 表示 index.js 文件里导出的 handler 函数。Python 中则是 app.lambda_handler。入口签名决定了事件对象与上下文对象如何传入,这是函数与事件源对接的契约。
运行时与层:把依赖从函数包中解耦
运行时是 Lambda 为函数提供的语言执行环境,分为托管运行时(如 Node.js、Python、Java、.NET、Go、Ruby)和自定义运行时(Custom Runtime,通过 provided.al2 等实现)。托管运行时由 AWS 负责打补丁和升级,自定义运行时则把控制权交给开发者,适合特殊语言或特定版本需求。
层(Layer)是解决依赖复用与包体积问题的关键机制。它把库、依赖或共享代码打包成独立归档,挂载到函数的 /opt 目录下。一个函数最多可挂载 5 个层,层与函数解耦后,多个函数可以共享同一份依赖,避免每个函数包都重复打包。层的内容在解压后会计入函数的可写空间限制,因此并非“免费”的依赖方案。
内存与超时调优:内存决定的不只是内存
Lambda 的内存配置范围是 128 MB 到 10240 MB,但内存并不是一个孤立的资源参数。在 Lambda 中,CPU 算力与内存成正比:内存越大,分配的 vCPU 越多。这意味着提高内存往往能缩短执行时间,从而可能降低总费用——因为计费按“GB-秒”计算,执行时间缩短可能抵消单价上升。调优的常见做法是:固定一个典型事件,逐步提高内存,观察执行时间与费用的变化曲线,找到性价比拐点。
超时时间范围为 1 秒到 900 秒(15 分钟)。超时设置过短会导致正常请求被中断,过长则会让异常请求长时间占用并发。一个实用原则是:超时时间应略大于 P99 执行时间,而不是简单设为最大值。对于调用外部服务的函数,超时还应考虑下游的响应时间与重试策略。
并发模型:按需、预留与预置
Lambda 的并发模型分为三种。按需并发(On-Demand)是默认模式,每个请求触发一个执行环境,区域默认并发上限为 1000,可通过服务配额申请提升。预留并发(Reserved Concurrency)为某个函数保留一个并发上限,既能防止该函数挤占其他函数的并发,也能限制其自身规模。预置并发(Provisioned Concurrency)则提前初始化指定数量的执行环境,使这些环境在调用时直接进入热状态,从而消除冷启动。
需要区分的是:预留并发是“上限”,预置并发是“预热”。两者可以配合使用,但预置并发需要额外付费。
冷启动原理与缓解策略
冷启动发生在 Lambda 需要为新请求创建执行环境时。其路径包括:下载代码与层、启动运行时、执行初始化代码(Init)、然后才进入 Handler。冷启动耗时主要集中在前三步,尤其是包体积大、依赖多、初始化逻辑重的情况下。热调用则复用已有执行环境,不再重复这些步骤。
缓解冷启动的常见策略包括:精简部署包与层,减少下载与解压时间;在 Init 阶段复用数据库连接、HTTP 客户端等重对象;适当提高内存以换取更多 CPU;对延迟敏感的函数使用预置并发;避免不必要的 VPC 配置,因为 VPC 环境创建会额外增加冷启动时间。需要强调的是,冷启动无法被完全消除,只能被管理和缓解。
一个可参考的调优检查清单
| 检查项 | 观察指标 | 调整方向 |
|---|---|---|
| 包体积与层数量 | Init Duration | 精简依赖,合并或移除冗余层 |
| 内存配置 | Duration、费用 | 逐步提高,找性价比拐点 |
| 超时时间 | Errors、Timeout | 设为略大于 P99 执行时间 |
| 并发模式 | ConcurrentExecutions、Throttles | 按需/预留/预置组合 |
| VPC 配置 | Init Duration | 非必要不启用 VPC |