170 lines
6.0 KiB
Markdown
170 lines
6.0 KiB
Markdown
# 第18天:SQS 与 SNS——消息队列和通知服务
|
||
|
||
## 今天你将学到什么
|
||
|
||
今天学习两个让系统"松耦合"的服务:SQS(消息队列)和 SNS(通知服务)。它们解决的核心问题是:**让系统的各个部分不再紧密依赖,一个部分出问题不会拖垮整个系统。**
|
||
|
||
---
|
||
|
||
## 为什么需要消息队列——用餐厅来理解
|
||
|
||
### 没有消息队列的世界(紧耦合)
|
||
|
||
想象一个餐厅,流程是这样的:
|
||
|
||
顾客点单 → 服务员站在厨房门口等 → 厨师做好菜 → 服务员端菜上桌 → 服务员回来接下一个顾客
|
||
|
||
**问题**:
|
||
- 服务员在等厨师做菜的时候什么都干不了(阻塞)
|
||
- 如果厨师突然肚子疼去了厕所,服务员和顾客都得干等(一个环节故障影响全部)
|
||
- 午餐高峰期 100 个人同时点单,厨房根本忙不过来(没有缓冲)
|
||
|
||
### 有消息队列的世界(松耦合)
|
||
|
||
改进后的流程:
|
||
|
||
顾客点单 → 服务员把订单**贴在窗口**(消息队列)→ 服务员立刻回去服务下一个顾客
|
||
|
||
厨师按自己的节奏从窗口**取订单**做菜 → 做好了放在出菜口 → 服务员来取
|
||
|
||
**好处**:
|
||
- 服务员不用等厨师(异步,不阻塞)
|
||
- 厨师去厕所了?订单还贴在窗口,回来继续做(容错)
|
||
- 高峰期订单堆在窗口,厨师按自己的速度做,不会崩溃(削峰)
|
||
- 可以加更多厨师来加快速度(水平扩展)
|
||
|
||
**这就是消息队列的价值。**
|
||
|
||
---
|
||
|
||
## SQS(Simple Queue Service)
|
||
|
||
SQS 是 AWS 的消息队列服务——一个"订单窗口"。
|
||
|
||
### 工作流程
|
||
|
||
```
|
||
生产者(发送消息的人)→ SQS 队列 → 消费者(处理消息的人)
|
||
```
|
||
|
||
**举个真实例子**:电商下单流程
|
||
|
||
用户点击"提交订单"后,需要做很多事:
|
||
1. 扣减库存
|
||
2. 发送确认短信
|
||
3. 生成物流单
|
||
4. 更新用户积分
|
||
5. 通知仓库备货
|
||
|
||
**没有 SQS**:所有步骤串行执行。用户要等所有步骤完成才看到"下单成功"。任何一步失败,整个订单失败。
|
||
|
||
**有 SQS**:
|
||
- 订单创建成功后立刻返回"下单成功"给用户(用户不用等)
|
||
- 同时把"有新订单"这个消息发到 SQS 队列
|
||
- 库存服务、短信服务、物流服务各自从队列取消息处理
|
||
- 某个服务暂时挂了?消息还在队列里,恢复后继续处理
|
||
|
||
### SQS 的关键特性
|
||
|
||
**消息保留**:消息最多保留 14 天。如果 14 天内没人处理,才会被删除。
|
||
|
||
**可见性超时**:消费者取走一条消息后,这条消息对其他消费者"隐藏"一段时间。如果消费者处理成功就删除消息;如果处理失败(比如消费者崩溃了),超时后消息重新出现,可以被其他消费者重试。
|
||
|
||
**死信队列**:如果一条消息反复处理失败(比如重试了 5 次都失败),自动转移到"死信队列"。你可以人工检查这些"问题消息",避免它们阻塞正常处理。
|
||
|
||
---
|
||
|
||
## SNS(Simple Notification Service)
|
||
|
||
SNS 是"发布/订阅"模式的通知服务——一条消息可以同时发给多个接收者。
|
||
|
||
### SQS vs SNS 的区别
|
||
|
||
**SQS = 点对点**(一条消息只被一个消费者处理)
|
||
- 类比:快递柜。一个包裹只能被一个人取走。
|
||
|
||
**SNS = 广播**(一条消息发给所有订阅者)
|
||
- 类比:小区广播。一条通知所有住户都能听到。
|
||
|
||
### SNS 的工作方式
|
||
|
||
```
|
||
发布者 → SNS 主题(Topic)→ 订阅者 A(邮箱)
|
||
→ 订阅者 B(短信)
|
||
→ 订阅者 C(SQS 队列)
|
||
→ 订阅者 D(Lambda 函数)
|
||
→ 订阅者 E(HTTP 接口)
|
||
```
|
||
|
||
**举个例子**:用户注册成功后
|
||
|
||
```
|
||
用户注册成功 → 发布"新用户注册"事件到 SNS
|
||
→ 邮件服务收到 → 发送欢迎邮件
|
||
→ 积分服务收到 → 赠送新人积分
|
||
→ 推荐服务收到 → 生成个性化推荐
|
||
→ 数据分析收到 → 记录注册统计
|
||
```
|
||
|
||
一个事件,多个服务各自处理自己关心的部分。互不影响。
|
||
|
||
---
|
||
|
||
## 经典组合:SNS + SQS(扇出模式)
|
||
|
||
这是 AWS 最推荐的异步架构模式:
|
||
|
||
```
|
||
订单服务发布"新订单"事件
|
||
↓
|
||
SNS 主题(广播给所有订阅者)
|
||
├── SQS 队列 A → 库存服务(扣减库存)
|
||
├── SQS 队列 B → 通知服务(发短信/邮件)
|
||
├── SQS 队列 C → 物流服务(生成运单)
|
||
└── SQS 队列 D → 积分服务(加积分)
|
||
```
|
||
|
||
**为什么中间要加 SQS,不直接用 SNS 推给各服务?**
|
||
|
||
因为 SQS 提供了"缓冲"和"重试":
|
||
- 某个服务暂时挂了 → 消息在 SQS 里等着,恢复后继续处理
|
||
- 某个服务处理慢 → 消息在 SQS 里排队,不会丢失
|
||
- 流量突然暴涨 → SQS 帮你削峰,各服务按自己的速度消费
|
||
|
||
---
|
||
|
||
## 同步 vs 异步:什么时候用哪种
|
||
|
||
| 场景 | 方式 | 原因 |
|
||
|------|------|------|
|
||
| 用户查询商品详情 | 同步 | 用户在等结果,必须立刻返回 |
|
||
| 用户下单扣库存 | 同步 | 必须确认库存够才能下单 |
|
||
| 下单后发确认短信 | 异步 | 短信晚几秒发不影响下单结果 |
|
||
| 下单后更新推荐 | 异步 | 推荐更新慢一点无所谓 |
|
||
| 上传图片后生成缩略图 | 异步 | 缩略图不需要立刻生成 |
|
||
|
||
**判断标准**:用户是否在等这个结果?如果是,同步。如果不是,异步。
|
||
|
||
---
|
||
|
||
## 今天的小测验
|
||
|
||
1. 消息队列解决的核心问题是什么?用你自己的话解释。
|
||
2. SQS 和 SNS 的区别是什么?各自适合什么场景?
|
||
3. 什么是"死信队列"?它解决什么问题?
|
||
4. 为什么说"SNS + SQS"是最佳组合?
|
||
|
||
---
|
||
|
||
## 延伸阅读
|
||
|
||
- [SQS 开发者指南](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/)
|
||
- [SNS 开发者指南](https://docs.aws.amazon.com/sns/latest/dg/)
|
||
- [AWS 消息传递模式](https://aws.amazon.com/messaging/)
|
||
|
||
---
|
||
|
||
## 明天预告
|
||
|
||
明天是第二阶段的收尾:用一个完整的项目案例,把这 11 天学到的所有核心服务串联起来,看看它们在真实架构中是怎么配合工作的。
|