5月27日 16:46
Serverless API 设计有哪些最佳实践?
Serverless 架构改变了 API 的设计与运维方式——函数无状态、冷启动不可控、弹性伸缩自动发生。这些特性决定了 API 设计不能照搬传统单体或微服务思路,需要从请求模型、网关配置、性能策略三个层面重新审视。
API 设计核心原则
RESTful 设计规范
Serverless 函数粒度小、生命周期短,RESTful 风格的约束刚好与之契合:
- 资源导向路由:用名词表示资源(
/users、/orders),用 HTTP 方法表达操作(GET 查询、POST 创建、PUT 更新、DELETE 删除)。避免在路径中混入动词,如/getUser或/deleteOrder。 - 统一接口约定:所有端点遵循相同的请求/响应格式,状态码语义一致——201 表示创建成功,204 表示删除成功,422 表示参数校验失败。前端或调用方不需要为每个接口写特殊处理逻辑。
- 版本控制:将版本号放在 URL 路径(
/v1/users)或请求头(Accept: application/vnd.api.v1+json)中。路径版本更直观,适合对外公开 API;请求头版本更 RESTful,适合内部服务。
无状态设计
无状态是 Serverless 的底层约束,API 设计必须顺应这一点:
- 会话管理:不在函数内存中保存会话状态。使用 JWT Token 将用户信息编码在令牌本身,或用 Redis/DynamoDB 等外部存储托管 session。每次请求携带完整认证信息,函数实例之间无需共享内存。
- 请求独立性:每个请求自包含所有必要上下文——认证信息、请求参数、关联 ID。不要假设同一用户的连续请求会命中同一个函数实例。
- 幂等性保障:对于写操作,确保相同的请求重复执行不会产生副作用。创建操作用幂等键(idempotency key)去重,更新操作用条件写入(如 DynamoDB 的 ConditionExpression)防止并发覆盖。
性能优化策略
冷启动和按调用计费是 Serverless 的两个痛点,性能优化围绕它们展开:
- 响应缓存:对读多写少的接口,在 API Gateway 层启用缓存(TTL 按数据更新频率设置),或在前方部署 CloudFront/CDN 缓存完整响应。这能大幅减少函数调用次数,降低冷启动概率和费用。
- 批量操作支持:设计批量端点(
POST /users/batch),允许单次请求处理多条记录,减少函数调用次数和网络往返。批量上限要合理设置,避免超时。 - 异步处理:耗时操作(报表生成、邮件发送、文件转码)不要同步等待。API 立即返回 202 Accepted 和一个任务 ID,后台通过 Step Functions 或 SQS 队列异步执行,客户端通过
GET /tasks/{id}轮询结果。
API Gateway 配置要点
API Gateway 是 Serverless API 的入口,配置质量直接影响安全性和可维护性。
路由配置
- 路径映射:将 HTTP 路径和方法映射到对应的 Lambda 函数。合理组织路由结构,相关资源嵌套展示(
/users/{id}/orders),但避免过深嵌套(超过 3 层会增加理解成本)。 - 参数验证:在 API Gateway 层配置请求验证器(Request Validator),对路径参数、查询参数、请求体进行格式校验。不合法的请求在网关层就被拦截,不会触发函数调用,既节省费用又减少无效执行。
- 限流配置:设置 API 级别的限流策略(Throttling),包括速率上限(Rate)和突发上限(Burst)。对公开 API 尤其重要,防止个别消费者占用全部容量。
认证与授权
- API Key:最简单的认证方式,适合内部服务或受信调用方。API Key 通过请求头
x-api-key传递,API Gateway 直接校验,无需调用 Lambda。注意 API Key 不等同于安全认证,它更接近访问控制,应结合使用计划(Usage Plan)做配额管理。 - Amazon Cognito:托管用户池(User Pool),支持注册、登录、密码找回等用户管理流程。前端登录后拿到 JWT,API Gateway 自动验证令牌签名和过期时间,适合面向终端用户的 API。
- Lambda Authorizer:当认证逻辑超出 Cognito 能力范围时使用。Lambda 函数接收请求信息,执行自定义校验逻辑(如查询数据库、调用内部认证服务),返回 IAM 策略。适合企业内部 SSO、三方 OAuth 等复杂场景。
响应处理
- CORS 配置:浏览器跨域请求需要正确的 CORS 头。在 API Gateway 中配置
Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers。OPTIONS 预检请求也要正确响应,否则前端跨域调用会失败。 - 统一错误格式:所有错误响应遵循相同结构,例如
{"error": {"code": "VALIDATION_ERROR", "message": "..."}}。Lambda 函数抛出异常时,通过映射模板将错误统一转换为标准格式返回。 - 响应转换:使用映射模板(Mapping Template)转换 Lambda 返回值格式。例如函数返回业务数据,网关层自动包装成
{"data": ..., "meta": {...}}的信封格式,调用方无需关心函数内部结构。
交付级最佳实践
接口文档
使用 Swagger/OpenAPI 规范生成接口文档,确保文档与代码同步。AWS SAM 和 Serverless Framework 都支持在模板中内联定义 API Schema,部署时自动生成文档。文档应覆盖请求参数、响应格式、错误码、调用示例。
监控告警
关键指标必须持续监控:
- 调用量和错误率:通过 CloudWatch Metrics 跟踪 API 调用次数和 4xx/5xx 错误率。5xx 错误率超过阈值时触发告警。
- 响应时间:监控 P50/P95/P99 延迟,冷启动导致的延迟飙升需要及时捕获。
- 并发数和限流拒绝:观察并发执行数是否接近账户限额,被限流拒绝的请求数是否异常增长。
安全防护
- WAF 配置:在 API Gateway 前部署 AWS WAF,防护 SQL 注入、XSS 跨站脚本、异常流量等常见攻击。设置 IP 黑名单和地理限制,阻断已知恶意来源。
- 最小权限原则:Lambda 函数的 IAM Role 只授予必要的权限,禁止使用
*:*全通配策略。 - 敏感数据保护:不在 URL 路径或查询参数中传递敏感信息(密钥、Token),使用请求头或请求体。启用 API Gateway 的请求日志时,注意脱敏处理。
测试覆盖
为每个 API 端点编写测试用例,覆盖正常路径和边界情况:
- 单元测试:验证 Lambda 函数的逻辑正确性,Mock 外部依赖。
- 集成测试:通过 API Gateway 的测试调用功能,验证端到端流程。
- 契约测试:确保 API 的请求/响应格式符合 OpenAPI 定义,防止破坏性变更。
Serverless 架构下 API 设计的核心思路是:把无状态约束当作设计原则而非限制,让每个请求自包含,让 API Gateway 承担更多网关层的职责,把函数专注于业务逻辑。