Lambda 无服务器计算
AWS Lambda 是事件驱动的无服务器计算服务,让你无需管理服务器即可运行代码。
核心概念
什么是无服务器(Serverless)
无服务器不是没有服务器,而是指:
- 开发者无需管理服务器
- 按实际执行时间付费
- 自动扩展,无需配置
- 高可用性内置
Lambda 架构
触发器(Trigger)
│
├─ API Gateway HTTP 请求触发
├─ S3 Event 文件上传触发
├─ DynamoDB Stream 数据变更触发
├─ CloudWatch Event 定时任务触发
├─ SNS/SQS 消息队列触发
└─ EventBridge 事件总线触发
│
▼
Lambda 函数
│
├─ 执行环境(Runtime)
│ ├─ Python 3.x
│ ├─ Node.js 18.x
│ ├─ Java 17
│ ├─ Go 1.x
│ └─ Custom Runtime
│
├─ 执行上下文
│ ├─ 内存:128MB - 10GB
│ ├─ 超时:最长 15 分钟
│ ├─ 临时存储:/tmp(最大 10GB)
│ └─ 环境变量
│
└─ IAM 角色权限
│
▼
输出/集成
├─ 返回结果
├─ 调用其他服务
├─ 写入数据库
└─ 发送通知
Lambda 的工作原理
冷启动与热启动
冷启动(Cold Start):
- 下载代码包
- 启动执行环境
- 初始化运行时
- 执行初始化代码
- 执行函数代码
耗时:Java 约 1-5 秒,Python/Node.js 约 100-500ms
热启动(Warm Start):
- 复用已有的执行环境
- 直接执行函数代码
- 耗时:通常 < 10ms
优化策略:
- 使用 Provisioned Concurrency(预配置并发)
- 减小部署包大小
- 最小化初始化代码
- 选择启动快的运行时(Python、Node.js)
并发模型
请求流量
│
├─ 1000 并发请求
│
▼
Lambda 服务
│
├─ 创建 1000 个执行环境
├─ 每个处理 1 个请求
├─ 并发上限:
│ ├─ 账户默认:1000
│ ├─ 可申请提升至 10,000+
│ └─ 预留并发(Reserved Concurrency)
│
└─ 空闲后保留 5-15 分钟
并发类型:
- Unreserved(未预留):与其他函数共享账户并发
- Reserved(预留):专属并发,不与其他函数共享
- Provisioned(预配置):预先初始化,消除冷启动
使用场景
1. Web API 后端
客户端 → API Gateway → Lambda → DynamoDB
↓
CloudWatch Logs
优势:
- 自动扩展应对流量峰值
- 按请求付费,低成本
- 无需管理服务器
示例架构:
# Lambda Handler
def lambda_handler(event, context):
# 解析 API Gateway 请求
http_method = event['httpMethod']
path = event['path']
body = json.loads(event['body']) if event['body'] else {}
# 业务逻辑
if http_method == 'GET':
result = get_data(path)
elif http_method == 'POST':
result = create_data(body)
# 返回响应
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps(result)
}
2. 数据处理流水线
S3 上传 → Lambda(数据转换) → S3 存储
↓
Lambda(生成缩略图)
↓
S3 存储缩略图
场景:
- 图片/视频处理
- 日志分析
- ETL 任务
- 实时数据转换
3. 定时任务(Cron Jobs)
CloudWatch Events (Cron) → Lambda → 执行任务
↓
发送通知/报告
示例:
- 每日数据备份
- 定期清理过期数据
- 生成业务报表
- 健康检查和监控
4. 事件驱动应用
DynamoDB Streams → Lambda → 同步到 Elasticsearch
SNS Topic → Lambda → 发送邮件/短信
SQS Queue → Lambda → 异步处理任务
Lambda 最佳实践
1. 函数设计原则
单一职责:
- 每个函数只做一件事
- 易于测试和维护
- 便于独立扩展
无状态设计:
- 不依赖本地存储
- 使用 S3/DynamoDB 存储状态
- 每次调用独立执行
快速执行:
- 控制执行时间 < 30 秒
- 长任务拆分为多个小任务
- 使用 Step Functions 编排复杂流程
2. 性能优化
减少冷启动:
# ❌ 不好:每次都初始化
def lambda_handler(event, context):
import boto3
s3 = boto3.client('s3')
# ...
# ✅ 好:在函数外初始化(复用)
import boto3
s3 = boto3.client('s3')
def lambda_handler(event, context):
# 使用已初始化的 s3 客户端
# ...
合理配置内存:
- 内存越大,CPU 性能越强
- 增加内存可能降低总成本(执行更快)
- 使用 Lambda Power Tuning 工具优化
连接池复用:
# 数据库连接复用
import pymysql
# 全局连接(在函数外)
connection = None
def get_connection():
global connection
if connection is None:
connection = pymysql.connect(
host='database.example.com',
user='admin',
password='password',
database='mydb'
)
return connection
def lambda_handler(event, context):
conn = get_connection()
# 使用连接...
3. 错误处理
重试策略:
def lambda_handler(event, context):
max_retries = 3
retry_count = 0
while retry_count < max_retries:
try:
result = process_data(event)
return result
except Exception as e:
retry_count += 1
if retry_count >= max_retries:
# 发送到 DLQ(死信队列)
send_to_dlq(event, str(e))
raise
time.sleep(2 ** retry_count) # 指数退避
死信队列(DLQ):
- 捕获失败的事件
- 便于调试和重新处理
- 使用 SQS 或 SNS
4. 安全实践
最小权限原则:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-bucket/uploads/*"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:GetItem"
],
"Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/MyTable"
}
]
}
敏感数据管理:
- 使用环境变量(加密)
- 使用 Secrets Manager 或 Parameter Store
- 不在代码中硬编码密钥
Lambda 定价
计费模型
请求数:
- 前 100 万次请求/月:免费
- 之后:$0.20 / 100 万次请求
执行时间:
- 前 40 万 GB-秒/月:免费
- 之后:$0.0000166667 / GB-秒
GB-秒计算:
执行时间(秒) × 内存(GB) = GB-秒
示例:
- 1000 次请求
- 每次执行 200ms (0.2秒)
- 内存 512MB (0.5GB)
总 GB-秒 = 1000 × 0.2 × 0.5 = 100 GB-秒
成本 ≈ 100 × $0.0000166667 = $0.00167
成本优化
选择合适的内存:
- 内存越大,CPU 越强,但单价越高
- 找到性能/成本的最佳平衡点
使用 ARM(Graviton2):
- 比 x86 便宜 20%
- 性能相当或更好
- 适合计算密集型任务
预留并发(Provisioned Concurrency):
- 消除冷启动
- 但会增加成本(按预留时间计费)
- 仅在需要低延迟时使用
Lambda 限制
执行限制
| 限制项 | 值 |
|---|---|
| 内存 | 128 MB - 10 GB |
| 临时存储(/tmp) | 512 MB - 10 GB |
| 超时 | 最长 15 分钟 |
| 环境变量 | 4 KB |
| 部署包大小(压缩) | 50 MB |
| 部署包大小(解压) | 250 MB |
| 并发执行数 | 默认 1000(可申请提升) |
网络限制
- VPC Lambda:需要 NAT Gateway 访问互联网
- 公网 Lambda:无法访问 VPC 内资源(除非配置 VPC)
- 出站连接:受 VPC 安全组和 NACL 限制
Lambda vs. 传统服务器
| 维度 | Lambda | EC2 |
|---|---|---|
| 成本 | 按执行时间付费,低流量低成本 | 按小时付费,一直运行 |
| 扩展 | 自动扩展,无需配置 | 需配置 Auto Scaling |
| 维护 | 零维护,AWS 管理 | 需打补丁、更新系统 |
| 启动 | 毫秒级(热启动) | 分钟级 |
| 长任务 | 最长 15 分钟 | 无限制 |
| 状态 | 无状态 | 可有状态 |
| 冷启动 | 存在冷启动延迟 | 无冷启动 |
何时使用 Lambda
✅ 适合场景:
- 事件驱动的任务
- 短时间执行(< 15 分钟)
- 间歇性流量
- 需要快速扩展
- 不想管理服务器
❌ 不适合场景:
- 长时间运行任务(> 15 分钟)
- 需要持久连接(WebSocket)
- 有状态应用
- 对冷启动敏感且高 QPS
- 需要专用硬件(GPU)
监控与调试
CloudWatch Logs
每个 Lambda 函数自动集成 CloudWatch Logs:
- 查看执行日志
- 监控错误和异常
- 分析性能指标
X-Ray 分布式追踪
启用 X-Ray 后可以:
- 可视化请求流程
- 识别性能瓶颈
- 分析服务依赖关系
关键指标
- Invocations:调用次数
- Duration:执行时间
- Errors:错误次数
- Throttles:限流次数
- Concurrent Executions:并发执行数
- Iterator Age:事件处理延迟(流处理)
Lambda 是构建现代无服务器应用的核心服务,掌握它是云原生开发的关键技能!