这是 Beta 探索课程,内容结构、实验步骤和示例可能会继续调整。
削峰填谷
场景
某个大型活动期间,流量暴增。
活动概况
活动
双 11 促销
客户类型
大量电商客户
持续时间
24 小时
平时流量
10 万次/天
活动流量
100 万次/天
10 倍增长
峰值流量
平时 QPS 的 20 倍
问题分析
流量分析
流量对比:
平时
日均 10 万次/天
QPS 1.2 次/秒
活动期间
日均 100 万次/天
QPS 11.5 次/秒
峰值 200 次/秒(持续 10 分钟)
系统容量:
数据库
50 次/秒
应用服务器
100 次/秒
结论: 峰值流量(200 次/秒)远超系统容量(数据库 50 + 应用 100 = 150 次/秒)
解决方案:消息队列
架构演进:同步 vs 异步
同步处理(之前)
用户请求
应用服务器
数据库(阻塞等待)
异步处理(现在)
用户请求
应用服务器
消息队列
立即返回(接受)
后端消费 & 写入数据库
实现
1. 消息队列选择
使用 RabbitMQ:
为什么选择 RabbitMQ:
- 可靠性高(持久化、确认机制)
- 支持多种消息模式
- 社区活跃
- 有管理界面选型边界
为什么用 RabbitMQ 做削峰
- 触发问题
- 活动流量在短时间内冲高,后端处理能力稳定但入口瞬时请求远超容量,需要把“接收请求”和“处理任务”解耦。
- 候选方案
- 应用内队列、Redis Stream、RabbitMQ、Kafka、直接扩容应用实例。
- 选择理由
- RabbitMQ 的确认、持久化和死信队列更适合当前这种任务可靠投递场景,运维复杂度也低于 Kafka。
- 代价
- 用户无法立即拿到最终结果,需要设计任务状态查询、重试、超时和失败提示。
- 暂不解决
- 暂不做大规模日志流式处理;如果未来吞吐变成百万级持续写入,再评估 Kafka。
2. 队列设计
设计流程
2. 队列设计
- 步骤 1:写入队列并异步消费任务
- 步骤 2:准备流量入口、防护规则、队列容量和降级开关
- 步骤 3:写入队列并异步消费任务
- 步骤 4:写入队列并异步消费任务
关注点:入口保护、核心服务可用性、误伤率和容量余量。
3. API 处理改为异步
设计流程
3. API 处理改为异步
- 步骤 1:识别突发流量或攻击特征,并执行防护策略
- 步骤 2:更新限流、排队、降级或防护策略
- 步骤 3:写入队列并异步消费任务
- 步骤 4:刷新防护规则、热点数据或排队状态
关注点:入口保护、核心服务可用性、误伤率和容量余量。
4. 查询结果
设计流程
4. 查询结果
- 步骤 1:更新限流、排队、降级或防护策略
- 步骤 2:刷新防护规则、热点数据或排队状态
- 步骤 3:写入队列并异步消费
- 步骤 4:校验身份、密钥或权限
关注点:入口保护、核心服务可用性、误伤率和容量余量。
队列管理
监控队列长度
设计流程
监控队列长度
- 步骤 1:检查健康状态并触发告警
- 步骤 2:写入队列并异步消费
- 步骤 3:采集健康状态并触发告警
关注点:入口保护、核心服务可用性、误伤率和容量余量。
上线前多想一步
- 队列最多能堆多少? 堆积不是越多越好,超过某个数量就应该限流或降级。
- 任务失败重试几次? 一直重试会拖垮队列,重试完还失败要进入人工可查的列表。
- 用户怎么看进度? 异步处理后,页面要能告诉用户“处理中、成功、失败”,不能只让用户等。