
译者前言:Serverless 架构的 demo 遍地都是,但真正能上生产的少。这篇文章的作者直接给出了 CloudFront + S3 + API Gateway + Lambda + DynamoDB + Cognito + WAF 的完整方案,包括 CI/CD 分开流水线、Lambda 版本 + 别名滚动发布、SPA 路由的 CloudFront Function 代码——这是那种你拿来就能落地的生产级指南。
为了使架构具体,我将使用一个单页 Web 应用(SPA)配合 serverless 后端:
浏览器请求 https://app.example.com,请求到达 CloudFront,CloudFront 提供缓存的 index.html(短 TTL)和版本化的 JS/CSS bundles(长 TTL,不可变)。只有在缓存未命中时 CloudFront 才从 S3 获取。
前端重定向到 Cognito Hosted UI(或使用 Cognito SDK),Cognito 认证用户并返回 JWT(ID token / access token),前端安全存储令牌(强烈建议使用 Authorization Code + PKCE)。
浏览器调用 https://api.example.com/projects,发送 Authorization: Bearer JWT。
Cognito 授权器验证签名、颁发者和受众,令牌无效/过期时提前拒绝请求。
Lambda 从 API Gateway 请求上下文读取认证上下文(用户 claims),运行应用级授权检查,读写 DynamoDB。
API Gateway 返回 JSON 响应,浏览器渲染更新后的 UI,可观测性数据流向 CloudWatch / X-Ray。
对哈希化静态资产激进缓存,但让 index.html 保持较短 TTL 以便新版本快速可见。
index.html(短 TTL):Cache-Control: public, max-age=60, s-maxage=60,让 CloudFront 短暂缓存,同时允许新部署快速生效。
版本化资产(/assets/*.js、/assets/*.css):Cache-Control: public, max-age=31536000, immutable,文件名变化时无需失效。
对于 SPA,像 /dashboard/settings 这样的深链接应返回 index.html 而不是 S3 的 404。我通常用 CloudFront Function 解决这个问题。
随着应用增长,后端比前端更难运营。按领域边界分离 API 表面有助于管理所有权、部署和安全策略。
至少使用:app.example.com -> CloudFront + S3,api.example.com -> API Gateway。这提供了独立的缓存和安全控制、更干净的 CORS 配置、更清晰的可观测性和事件范围。
对于更大规模系统,按业务领域分离 API:users.api.example.com、projects.api.example.com、billing.api.example.com,或保持单一主机通过基础路径分割。
认证是"serverless demo"和"生产级"经常分道的地方。我选择对浏览器应用安全且易于在后端验证的流程。
我不将 JWT 验证当作完整授权。Lambda 仍然检查:租户范围、角色/组 claims、资源所有权、操作级权限。那是生产安全之所在。
在生产环境中,我不依赖单一机制进行滥用保护。我组合使用 WAF、API Gateway 限流和(可选)Lambda 并发控制。
我用 WAF 处理常见漏洞模式(托管规则组)、IP 信誉/机器人信号、请求大小约束、对明显滥用基于速率的屏蔽、地理限制(如适用)。
我用 API Gateway 限流保护后端容量免受突发影响:阶段级默认值、昂贵端点的路由/方法级覆盖。
对于特别危险的功能,我有时设置保留并发来限制爆炸半径。这不是限流的替代品,但保护下游系统和预算。
这一节是我看到 demo 架构和真实运营之间最大差距的地方。
前端流水线(CloudFront + S3):构建静态资产 -> 运行测试/lint -> 上传版本化资产到 S3 -> 最后上传 index.html -> 使 CloudFront 的 index.html 失效 -> 冒烟测试 app.example.com
后端流水线(API Gateway + Lambda + DynamoDB 变更):运行单元/集成测试 -> 构建 Lambda artifacts -> 部署基础设施变更 -> 使用版本 + 别名部署 Lambda 代码 -> Canary/线性发布 -> 冒烟测试 api.example.com -> 自动提升或回滚
如果先上传 index.html,用户可能收到引用尚未上传资产的 HTML。最后上传哈希化资产可以防止这种竞态条件。
如果我保持部署不可变,前端回滚通常很容易:每个构建输出唯一的文件名,S3 版本控制已启用,index.html 是发布指针。回滚选项:重新上传之前的 index.html、恢复之前 S3 对象版本、重新运行之前发布 artifact 的流水线。
后端回滚更复杂,因为 API 和数据会演进。我使用 Lambda 版本 + 别名 + CodeDeploy canary/线性部署 + 自动化回滚(针对 elevated 5xx、延迟峰值、告警违规)。
生产级 AWS Serverless Web 应用架构不是关于使用更多服务。而是选择明确的边界和安全默认值。
对我来说,制胜组合是:CloudFront + S3 用于快速、可缓存的前端交付;API Gateway + Lambda 用于清晰、独立可部署的后端逻辑;DynamoDB 用于低延迟扩展;Cognito 用于标准化认证;WAF + 限流用于分层保护;独立流水线 + 回滚设计用于运营信心。
如果我在早期就把缓存策略、认证边界和部署回滚模型做对了,随着应用增长,架构保持易于演进。