# 第32天:应用架构综合实战——设计一个 SaaS 平台 ## 今天你将学到什么 今天是第四阶段的收尾。我们用一个完整的 SaaS(软件即服务)平台案例,把容器、CI/CD、API Gateway、Step Functions、微服务等知识串联起来。 --- ## 项目背景:在线协作文档平台 假设你要做一个类似"腾讯文档"的简化版平台: - 用户可以创建、编辑、分享文档 - 支持多人实时协作编辑 - 支持文档导出为 PDF - 有团队管理和权限控制 - 需要支持百万级用户 --- ## 整体架构 ``` Web 前端 / 移动端 ↓ CloudFront(静态资源 + API 加速) ↓ API Gateway(REST API 入口) ↓ ┌─────────────────────────────────────────────────┐ │ ECS Fargate 集群 │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 用户服务 │ │ 文档服务 │ │ 团队服务 │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ ┌──────────┐ ┌──────────┐ │ │ │ 权限服务 │ │ 搜索服务 │ │ │ └──────────┘ └──────────┘ │ └─────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────┐ │ 数据层 │ │ Aurora(用户、团队、权限) │ │ DynamoDB(文档内容、版本历史) │ │ ElastiCache Redis(会话、协作状态) │ │ S3(文档附件、导出的 PDF) │ │ OpenSearch(全文搜索) │ └─────────────────────────────────────────────────┘ 异步处理: EventBridge → Step Functions → Lambda (文档导出、通知发送、数据分析) 实时协作: API Gateway WebSocket → Lambda → DynamoDB + Redis ``` --- ## 各服务职责 ### 用户服务 - 注册、登录、个人信息管理 - 集成 Cognito 做身份认证 - 数据库:Aurora(用户表) ### 文档服务 - 创建、读取、更新、删除文档 - 管理文档版本历史 - 数据库:DynamoDB(文档内容,支持高频读写) ### 团队服务 - 创建团队、邀请成员、管理角色 - 数据库:Aurora(团队和成员关系) ### 权限服务 - 判断用户对某个文档有没有权限 - 缓存:Redis(权限判断需要极快响应) ### 搜索服务 - 全文搜索文档内容和标题 - 引擎:OpenSearch(Elasticsearch 托管版) --- ## 关键流程设计 ### 流程一:用户编辑文档 ``` 1. 用户打开文档 → API Gateway → 权限服务(检查权限)→ 文档服务(获取内容) 2. 用户编辑 → WebSocket 连接 → Lambda → DynamoDB(保存变更) → Redis(广播给其他协作者) 3. 自动保存 → 每 5 秒将变更批量写入 DynamoDB → 保留版本历史(最近 100 个版本) ``` ### 流程二:文档导出 PDF(Step Functions) ``` 用户点击"导出 PDF" ↓ API Gateway → Lambda(创建导出任务)→ 返回任务 ID 给用户 ↓ Step Functions 工作流启动: ↓ 获取文档内容(Task) ↓ 渲染为 PDF(Task,可能需要 30 秒) ↓ 上传到 S3(Task) ↓ 生成下载链接(Task) ↓ 通知用户"PDF 已就绪"(Task → SNS → 推送通知) ``` 为什么用 Step Functions?因为 PDF 渲染可能需要较长时间,不适合让用户同步等待。 ### 流程三:新用户注册 ``` 用户注册 ↓ Cognito 创建用户 ↓ EventBridge 发布"用户注册"事件 ↓ ├── Lambda:创建默认工作空间 ├── Lambda:发送欢迎邮件(SES) ├── Lambda:创建示例文档 └── Lambda:记录注册统计 ``` --- ## CI/CD 流水线 ``` 开发者推送代码(GitHub) ↓ CodePipeline 触发 ↓ CodeBuild: - 运行单元测试 - 构建 Docker 镜像 - 推送到 ECR - 运行安全扫描 ↓ 部署到 Staging 环境: - 更新 ECS 服务 - 运行集成测试 - 运行 E2E 测试 ↓ 人工审批(团队负责人确认) ↓ 部署到 Production: - ECS 蓝绿部署 - 金丝雀发布(5% → 25% → 100%) - 自动回滚(如果错误率上升) ``` 每个微服务有自己独立的流水线,可以独立部署。 --- ## 扩展性设计 | 组件 | 扩展方式 | 触发条件 | |------|----------|----------| | ECS 服务 | 自动扩展任务数 | CPU > 70% 或请求队列增长 | | DynamoDB | 自动扩展读写容量 | 使用率 > 70% | | Aurora | 增加只读副本 | 读取延迟 > 100ms | | Redis | 增加分片 | 内存使用 > 80% | | Lambda | 自动(无需配置) | 并发请求增加 | --- ## 成本优化策略 | 策略 | 节省 | 实现方式 | |------|------|----------| | Fargate Spot | 最多 70% | 非关键服务使用 Spot 容量 | | DynamoDB 按需模式 | 避免过度预置 | 流量不稳定的表用按需模式 | | S3 生命周期 | 存储费用 | 30 天前的版本转到低频存储 | | CloudFront 缓存 | 减少源站请求 | 静态资源缓存 24 小时 | | Reserved Capacity | 最多 60% | Aurora 和 Redis 用预留实例 | --- ## 监控与告警 ``` CloudWatch Dashboard(统一视图): ├── 业务指标:活跃用户数、文档创建数、API 调用量 ├── 性能指标:API 延迟 P99、错误率、数据库连接数 ├── 资源指标:CPU、内存、磁盘使用率 └── 成本指标:每日花费、各服务占比 告警规则: ├── API 错误率 > 1% → 通知开发团队(Slack) ├── P99 延迟 > 2s → 通知运维团队 ├── 数据库连接数 > 80% → 自动扩展 + 通知 └── 月度成本超预算 20% → 通知管理层 ``` --- ## 架构决策总结 | 决策 | 选择 | 原因 | |------|------|------| | 服务运行 | ECS Fargate | 不想管服务器,按需付费 | | API 入口 | API Gateway | 统一认证、限流、监控 | | 实时协作 | WebSocket + Redis | 低延迟双向通信 | | 文档存储 | DynamoDB | 高频读写、灵活 schema | | 用户数据 | Aurora | 关系型数据、复杂查询 | | 异步处理 | EventBridge + Step Functions | 解耦、可视化、错误处理 | | 搜索 | OpenSearch | 全文搜索、模糊匹配 | | 部署 | 蓝绿 + 金丝雀 | 零停机、低风险 | --- ## 今天的小测验 1. 为什么文档内容用 DynamoDB 而不是 Aurora? 2. 文档导出 PDF 为什么用 Step Functions 而不是同步处理? 3. 这个架构中,哪些部分可以独立扩展? 4. 如果某个微服务出了 bug,对其他服务有什么影响? --- ## 延伸阅读 - [AWS SaaS 架构指南](https://docs.aws.amazon.com/whitepapers/latest/saas-architecture-fundamentals/saas-architecture-fundamentals.html) - [AWS 无服务器应用模型](https://docs.aws.amazon.com/serverless-application-model/) - [AWS 架构中心](https://aws.amazon.com/architecture/) --- ## 明天预告 进入第五阶段:监控与运维。明天学习 CloudWatch——AWS 的监控核心。了解如何监控你的应用和基础设施,设置告警,在问题发生前就发现它。