# 第31天:微服务架构——把大象拆成蚂蚁 ## 今天你将学到什么 今天学习微服务架构的核心思想和 AWS 上的实现方式。理解为什么大公司都在从"一个大应用"转向"多个小服务",以及这样做的好处和挑战。 --- ## 单体架构 vs 微服务架构 ### 单体架构(Monolith) 所有功能都在一个应用里: ``` 一个大应用: ├── 用户管理 ├── 商品管理 ├── 订单处理 ├── 支付处理 ├── 库存管理 ├── 通知服务 └── 数据分析 ``` **类比**:一家什么都卖的大超市。所有商品在一栋楼里,一个收银系统,一个仓库。 **优点**: - 开发简单(一个代码库,一个部署) - 本地调试方便 - 数据一致性容易保证 **缺点**: - 代码越来越大,新人要几周才能理解 - 改一个小功能要重新部署整个应用 - 一个模块的 bug 可能拖垮整个系统 - 不同模块不能独立扩展(订单模块需要 10 台服务器,但用户模块只需要 2 台) - 技术栈被锁定(整个应用必须用同一种语言) ### 微服务架构(Microservices) 每个功能是一个独立的小服务: ``` 用户服务(Python)──┐ 商品服务(Java)────┤ 订单服务(Go)──────┼── 通过 API 互相通信 支付服务(Node.js)─┤ 库存服务(Java)────┤ 通知服务(Python)──┘ ``` **类比**:一条商业街上的多家专卖店。鞋店只卖鞋,面包店只卖面包。每家店独立经营,互不影响。鞋店装修不影响面包店营业。 **优点**: - 每个服务小而专注,容易理解和维护 - 独立部署(改了订单服务只需要重新部署订单服务) - 独立扩展(订单服务压力大就多加几个实例) - 技术自由(每个服务可以用最适合的语言和框架) - 故障隔离(支付服务挂了,用户还能浏览商品) **缺点**: - 系统复杂度增加(服务间通信、数据一致性) - 运维难度增加(几十个服务要监控) - 调试困难(一个请求可能经过 5 个服务) - 网络延迟(服务间调用比函数调用慢) --- ## 什么时候该用微服务 ### 不要一开始就用微服务 **马丁·福勒(微服务概念的推广者)说过**:"几乎所有成功的微服务架构,都是从一个变得太大的单体应用演化而来的。" ### 判断标准 | 情况 | 建议 | |------|------| | 团队 < 5 人 | 单体架构 | | 应用刚起步 | 单体架构 | | 团队 > 20 人 | 考虑微服务 | | 不同模块需要不同扩展策略 | 考虑微服务 | | 部署频率需要很高 | 考虑微服务 | | 单体已经大到难以维护 | 考虑微服务 | --- ## 微服务在 AWS 上的实现 ### 服务运行方式 | 方式 | 适合 | AWS 服务 | |------|------|----------| | 容器 | 长时间运行的服务 | ECS / EKS + Fargate | | 无服务器 | 事件驱动、轻量服务 | Lambda + API Gateway | | 虚拟机 | 遗留应用、特殊需求 | EC2 + Auto Scaling | ### 服务间通信 | 方式 | 适合 | AWS 服务 | |------|------|----------| | 同步调用(HTTP/gRPC) | 需要立即得到结果 | ALB / API Gateway / App Mesh | | 异步消息 | 不需要立即结果 | SQS / SNS / EventBridge | | 事件流 | 实时数据流处理 | Kinesis / MSK(Kafka) | ### 服务发现 微服务之间怎么找到对方? **传统方式**:把每个服务的地址写在配置文件里。服务地址变了就要改配置。 **服务发现**:服务启动时自动注册自己的地址,其他服务通过名字查找。 ``` 订单服务想调用用户服务: → 问服务发现:"用户服务在哪?" → 服务发现回答:"10.0.1.25:8080 和 10.0.1.26:8080" → 订单服务选一个调用 ``` AWS 提供 **Cloud Map** 服务做服务发现。ECS 服务可以自动注册到 Cloud Map。 --- ## 微服务的数据管理 ### 每个服务拥有自己的数据库 这是微服务的核心原则之一: ``` ❌ 错误:所有服务共享一个数据库 用户服务 ─┐ 订单服务 ─┼── 同一个 MySQL 数据库 商品服务 ─┘ (一个服务改了表结构,其他服务可能崩溃) ✓ 正确:每个服务有自己的数据库 用户服务 → 用户数据库(RDS) 订单服务 → 订单数据库(DynamoDB) 商品服务 → 商品数据库(RDS) (互不影响,可以选择最适合的数据库类型) ``` ### 数据一致性挑战 当一个操作涉及多个服务时,如何保证数据一致? **举例**:用户下单需要同时扣库存和创建订单。 **解决方案:Saga 模式** ``` 1. 订单服务:创建订单(状态=待确认) 2. 库存服务:扣减库存 - 成功 → 订单服务:确认订单 - 失败 → 订单服务:取消订单(补偿操作) ``` 每一步都有对应的"补偿操作"。如果某一步失败,执行前面所有步骤的补偿操作来回滚。 Step Functions 非常适合实现 Saga 模式。 --- ## 微服务的可观测性 当一个请求经过 5 个服务时,出了问题怎么排查? ### 分布式追踪(AWS X-Ray) X-Ray 可以追踪一个请求在多个服务间的完整路径: ``` 用户请求 → API Gateway (5ms) → 订单服务 (20ms) → 库存服务 (15ms) → 支付服务 (200ms) ← 瓶颈在这里! → 通知服务 (10ms) ``` 一眼就能看出哪个服务慢了、哪里出了错。 ### 集中日志(CloudWatch Logs) 所有服务的日志发送到 CloudWatch Logs,统一查看和搜索。 ### 统一监控(CloudWatch) 所有服务的指标(CPU、内存、请求量、错误率)在一个仪表板上展示。 --- ## 微服务架构示例:电商平台 ``` 客户端 ↓ API Gateway(统一入口) ├── /users → 用户服务(ECS Fargate)→ Aurora ├── /products → 商品服务(ECS Fargate)→ DynamoDB ├── /orders → 订单服务(ECS Fargate)→ Aurora ├── /payments → 支付服务(Lambda)→ 外部支付网关 └── /notifications → 通知服务(Lambda)→ SES/SNS 服务间通信: 订单服务 → SNS "订单创建" 事件 → SQS → 库存服务(扣库存) → SQS → 通知服务(发通知) → SQS → 分析服务(记录数据) 服务发现:Cloud Map 分布式追踪:X-Ray 日志:CloudWatch Logs 监控:CloudWatch Dashboard ``` --- ## 今天的小测验 1. 单体架构和微服务架构各自的优缺点是什么? 2. 什么时候应该从单体转向微服务? 3. 微服务之间的同步通信和异步通信各自适合什么场景? 4. 为什么每个微服务应该有自己的数据库?这带来了什么挑战? --- ## 延伸阅读 - [AWS 微服务架构指南](https://docs.aws.amazon.com/whitepapers/latest/microservices-on-aws/microservices-on-aws.html) - [AWS X-Ray 开发者指南](https://docs.aws.amazon.com/xray/latest/devguide/) - [AWS Cloud Map](https://docs.aws.amazon.com/cloud-map/latest/dg/) --- ## 明天预告 明天是第四阶段的收尾:应用架构综合实战。我们会设计一个完整的微服务应用架构,把容器、CI/CD、API Gateway、Step Functions 等知识串联起来。