239 lines
7.2 KiB
Markdown
239 lines
7.2 KiB
Markdown
# 第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 等知识串联起来。
|