Lambda 与 API Gateway — CodeRoadMapLambda 与 API Gateway
无服务器与边缘。
Lambda 与 API Gateway
这一课你将能做到
- 创建并部署一个 Lambda 函数,通过 API Gateway 暴露为 HTTP 接口
- 理解 Lambda 的冷启动问题,并用 Provisioned Concurrency 优化
- 用 Lambda + API Gateway + DynamoDB 实现一个完整的 Serverless API
为什么要学
Lambda 是 AWS Serverless 的核心,让你「只写代码,不管服务器」。本站如果迁到 AWS,一些轻量级 API(如健康检查、数据上报、图片处理)用 Lambda 比 EC2 更省钱、更省心。面试中「Lambda 冷启动怎么解决」「API Gateway 和 ALB 怎么选」「Serverless 适合什么场景」是高频问题。
人话:Lambda 就是「函数即服务」。你写一个函数,AWS 帮你跑。没有服务器要管,没有系统要装,按调用次数和运行时间收费。闲时一分不收,忙时自动扩容到几千并发。
先建立图像
Lambda 执行模型:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ API GW │────→│ Lambda │────→│ DynamoDB │
│ (HTTP请求) │ │ (业务逻辑) │ │ (持久化) │
└─────────────┘ └─────────────┘ └─────────────┘
│
┌──────┴──────┐
│ 冷启动 │
│ 1. 下载代码 │
│ 2. 启动运行时 │
│ 3. 执行初始化 │
│ 4. 执行 handler│
└─────────────┘
Lambda vs EC2 对比:
| 维度 | Lambda | EC2 |
|---|
| 计费 | 按调用次数 + 执行时间 | 按小时/秒 |
| 并发 | 默认 1000,可提 | 取决于实例数 |
| 冷启动 | 有(ms 到秒级) | 无(常驻) |
| 运行时长 | 最长 15 分钟 | 无限 |
| 适合场景 | 事件驱动、突发流量、定时任务 | 常驻服务、长连接、大内存计算 |
| 内存 | 128MB - 10GB | 取决于实例类型 |
跟着做
步骤 1:创建 Lambda 函数(Python 示例)
创建 lambda_function.py:
import json
import boto3
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('UserCourseProgress')
def lambda_handler(event, context):
http_method = event['httpMethod']
path = event['path']
if http_method == 'GET' and '/progress' in path:
user_id = event['queryStringParameters']['userId']
response = table.query(
KeyConditionExpression='PK = :pk',
ExpressionAttributeValues={':pk': f'USER#{user_id}'}
)
return {
'statusCode': 200,
'headers': {'Content-Type': 'application/json'},
'body': json.dumps(response['Items'])
}
elif http_method == 'POST' and '/progress' in path:
body = json.loads(event['body'])
table.put_item(Item={
'PK': f"USER#{body['userId']}",
'SK': f"COURSE#{body['courseId']}",
'progress': body['progress']
})
return {
'statusCode': 201,
'body': json.dumps({'message': 'Progress saved'})
}
return {'statusCode': 404, 'body': json.dumps({'error': 'Not found'})}
# 打包
Compress-Archive -Path lambda_function.py -DestinationPath function.zip
# 创建 IAM Role(Lambda 执行角色)
aws iam create-role --role-name lambda-dynamodb-role --assume-role-policy-document '{"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Principal": {"Service": "lambda.amazonaws.com"}, "Action": "sts:AssumeRole"}]}'
aws iam attach-role-policy --role-name lambda-dynamodb-role --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
aws iam attach-role-policy --role-name lambda-dynamodb-role --policy-arn arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
# 创建 Lambda 函数
aws lambda create-function --function-name codenav-progress-api --runtime python3.12 --role arn:aws:iam::123456789012:role/lambda-dynamodb-role --handler lambda_function.lambda_handler --zip-file fileb://function.zip --timeout 30 --memory-size 256
步骤 2:创建 API Gateway
# 创建 REST API
aws apigateway create-rest-api --name codenav-api --description "CodeNav Progress API"
# 获取根资源 ID
aws apigateway get-resources --rest-api-id xxxxxxxx --query "items[0].id"
# 创建 /progress 资源
aws apigateway create-resource --rest-api-id xxxxxxxx --parent-id yyyyyyyy --path-part progress
# 创建 GET 方法
aws apigateway put-method --rest-api-id xxxxxxxx --resource-id zzzzzzzz --http-method GET --authorization-type NONE
# 设置 Lambda 集成
aws apigateway put-integration --rest-api-id xxxxxxxx --resource-id zzzzzzzz --http-method GET --type AWS_PROXY --integration-http-method POST --uri arn:aws:apigateway:ap-southeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-southeast-1:123456789012:function:codenav-progress-api/invocations
# 部署
aws apigateway create-deployment --rest-api-id xxxxxxxx --stage-name prod
步骤 3:测试 API
# 测试 GET
curl "https://xxxxxxxx.execute-api.ap-southeast-1.amazonaws.com/prod/progress?userId=1001"
# 测试 POST
curl -X POST "https://xxxxxxxx.execute-api.ap-southeast-1.amazonaws.com/prod/progress" -H "Content-Type: application/json" -d '{"userId": "1001", "courseId": "java-101", "progress": 80}'
步骤 4:配置 Provisioned Concurrency 解决冷启动
# 给函数版本分配预置并发(保持 5 个热实例)
aws lambda put-provisioned-concurrency-config --function-name codenav-progress-api --qualifier prod --provisioned-concurrent-executions 5
步骤 5:用 SAM/Serverless Framework 部署(推荐)
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
ProgressApi:
Type: AWS::Serverless::Api
Properties:
StageName: prod
ProgressFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/
Handler: lambda_function.lambda_handler
Runtime: python3.12
MemorySize: 256
Timeout: 30
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref ProgressTable
Events:
GetProgress:
Type: Api
Properties:
RestApiId: !Ref ProgressApi
Path: /progress
Method: get
ProgressTable:
Type: AWS::Serverless::SimpleTable
Properties:
PrimaryKey:
Name: PK
Type: String
# 部署
sam build
sam deploy --guided
讲清楚要点
- 冷启动(Cold Start):Lambda 首次调用或扩容时,需要下载代码、启动运行时、执行初始化代码(如 import boto3、创建数据库连接),耗时 100ms-数秒。Java/.NET 冷启动比 Python/Node.js 更明显。
- Provisioned Concurrency:预先保持 N 个热实例,消除冷启动。适合对延迟敏感的生产 API。代价是预置并发按小时收费,不管有没有调用。
- Lambda 内存与 CPU 的关系:Lambda 的 CPU 按内存比例分配。128MB 内存 ≈ 1/12 vCPU,1792MB 内存 = 1 vCPU,10240MB 内存 = 6 vCPU。内存越大,CPU 越多,执行越快,但单价越高。有时调大内存反而总成本更低(执行时间缩短)。
- API Gateway 类型:REST API(功能全,支持 API Key、请求验证)、HTTP API(便宜 70%,延迟低,功能少)、WebSocket API(长连接)。简单 CRUD 用 HTTP API 即可。
- Lambda 的 15 分钟限制:单次执行最长 15 分钟。长任务要拆成多个 Lambda(Step Functions 编排),或改用 ECS/Fargate。
你可能会懵的地方
-
Lambda 能访问 VPC 内的 RDS 吗?
能,但需要把 Lambda 配置到 VPC 的私有子网。注意:Lambda 在 VPC 里默认不能访问公网(除非配 NAT Gateway),且会占用子网 IP(ENI)。冷启动时创建 ENI 会增加延迟。
-
Lambda 和 Fargate 怎么选?
Lambda:事件驱动、突发流量、执行短(<15分钟)、不想管任何基础设施。Fargate:常驻服务、长连接、需要自定义容器镜像、执行时间长。轻量 API 用 Lambda,复杂微服务用 Fargate。
-
Lambda 函数之间怎么共享代码?
用 Lambda Layer。把公共依赖(如 boto3、requests)打成 Layer,多个函数引用。Layer 最大 250MB(解压后)。
-
API Gateway 的 29 秒超时是怎么回事?
API Gateway 到后端(Lambda)的集成超时是 29 秒。如果 Lambda 执行超过 29 秒,API Gateway 返回 504。这是硬限制,不能调。长任务要异步化(API GW 先返回 202,Lambda 后台处理)。
-
Lambda 的临时磁盘 /tmp 有多大?
默认 512MB,最大 10240MB(可配置)。/tmp 在函数实例生命周期内保留,可以当缓存用。
错法对照
| 错法 | 问题 | 正解 |
|---|
| 在 handler 外初始化数据库连接 | 每次冷启动都新建连接,但复用时可能拿到断开的连接 | 在 handler 外初始化,但加重连逻辑;或用 RDS Proxy |
| 给所有 API 配 Provisioned Concurrency | 预置并发按小时收费,浪费钱 | 只给延迟敏感的核心 API 配 |
| Lambda 里跑长任务(>15分钟) | 超时失败 | 拆任务(Step Functions),或改用 ECS |
| 不设 DLQ(死信队列) | 失败事件丢失 | 给异步调用配 SQS DLQ |
| 一把梭用 Java 写 Lambda | 冷启动 5-10 秒,用户体验差 | 用 Python/Node.js,或 Java 配 SnapStart |
卡点急救
- Lambda 超时:检查内存是否太小(CPU 不足);检查是否有 VPC 配置导致 ENI 创建慢;检查下游服务(RDS/DynamoDB)是否慢。
- API Gateway 返回 502:Lambda 函数报错,或返回格式不对。检查 Lambda 日志(CloudWatch Logs),确保返回
{statusCode, body, headers}。
- 并发打满(Throttling):默认账户级并发 1000。用
aws lambda get-account-settings 查看。突发流量配 Reserved Concurrency 或申请提额。
面试常问
-
Lambda 冷启动怎么优化?
用 Provisioned Concurrency 保持热实例;减少部署包大小(剔除无用依赖);用 SnapStart(Java);避免 VPC 配置(除非必须访问 RDS);用更轻的运行时(Python/Node.js 比 Java 快)。
-
API Gateway 和 ALB 怎么选?
API Gateway:Serverless、按请求计费、内置认证/限流/缓存、适合 REST API。ALB:更便宜(高并发时)、支持 WebSocket、适合容器/EC2 后端。轻量 API 用 API GW,高并发微服务用 ALB。
-
Lambda 的并发模型是什么?
每个并发执行环境(Execution Environment)处理一个请求。默认账户级 1000 并发。函数级可以设 Reserved Concurrency(预留并发,也是上限)。超过并发限制的请求会被 Throttle(同步调用返回 429,异步调用重试)。
自测三问
- Lambda 的 15 分钟限制对架构设计有什么影响?长任务怎么办?
- Provisioned Concurrency 和 Reserved Concurrency 的区别是什么?
- 为什么 Lambda 配了 VPC 后冷启动会变慢?怎么解决?
小结一句话
Lambda 是 Serverless 的核心,按调用计费、自动扩缩容,但冷启动和 15 分钟限制是设计时必须考虑的边界。
延伸