aws-doc/课程/第四阶段-应用架构/第31天-微服务架构.md
2026-05-08 10:24:39 +08:00

239 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 第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 / MSKKafka |
### 服务发现
微服务之间怎么找到对方?
**传统方式**:把每个服务的地址写在配置文件里。服务地址变了就要改配置。
**服务发现**:服务启动时自动注册自己的地址,其他服务通过名字查找。
```
订单服务想调用用户服务:
→ 问服务发现:"用户服务在哪?"
→ 服务发现回答:"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 等知识串联起来。