限流中间件
限流要放在应用入口的第一道关卡,才能在请求打到数据库之前就把超额流量挡下来。这一节的关键不是限流算法本身,而是限流维度选谁、计数存在哪、拒绝时怎么给用户一个说得清楚的提示。
设计流程
实现限流中间件
- 步骤 1:从请求上下文取出 API Key 或用户标识,换算成本次要用的限流维度(用户、应用或 IP)
- 步骤 2:读取该维度在当前窗口的已用次数,与套餐配额比较,决定放行、排队还是拒绝
- 步骤 3:在 Redis 中用一段原子脚本完成计数自增与窗口过期设置,避免并发下超发
- 步骤 4:拒绝时返回 429 并带上可重试时间,同时把放行、拒绝、等待时长写入限流指标
关注点:限流维度选择、原子计数与拒绝提示的可理解性。
上线后,我观察了一周:
User 123 的调用变化
限流前:
- 每小时:15000 次
- 每秒:4.2 次
限流后(免费版 1 次/秒):
- 每小时:3600 次
- 每秒:1 次
- 被限流次数:11400 次/小时
整体性能提升
限流前:
- QPS:10
- 响应时间:150ms
- CPU 使用率:70%
限流后:
- QPS:5
- 响应时间:50ms
- CPU 使用率:30%
用户反馈
正常用户:
- "API 速度快了很多" ✅
User 123(被限流的用户):
- 收到通知,告知需要升级套餐
- 部分用户升级到付费版 ✅
- 部分用户减少调用频率 ✅
限流上线之后,真正的工作才刚开始:阈值定高了挡不住滥用,定低了会误杀正常用户。监控要能回答两个问题——现在拒了多少,以及拒的是不是不该拒的。
设计流程
监控和告警
- 步骤 1:持续采集限流放行数、拒绝数和等待时长,并按套餐与限流维度分开统计
- 步骤 2:对比各套餐的拒绝率与用户反馈,判断阈值是否误伤了正常调用
- 步骤 3:为单用户调用突增、整体拒绝率上升、限流器自身异常分别设置分级告警
- 步骤 4:定期抽样回看被拒绝的请求,据此调整免费版与付费版的阈值配置
关注点:拒绝率的可信度、误杀识别与告警分级。
上线前多想一步
- 误伤正常用户怎么办? 先观察被拒绝的请求里有没有正常使用场景,再调阈值。
- 拒绝时怎么提示? 返回“太频繁了,多久后再试”,比只返回错误码更容易被理解。
- 阈值怎么改? 免费版、付费版和内部用户最好能分开配置,不要写死在代码里。
发现内容有问题?
告诉我们哪里需要改进。
