限流是什么?用排队买票来理解
你有没有在节假日抢过火车票?
12306 知道,一旦放票,几千万人同时点击"提交订单",服务器根本扛不住。所以它不会让所有人都同时冲进系统,而是给你分配了一个"排队号码",按顺序处理。
限流(Rate Limiting)就是互联网的"排队号码"机制——它限制单位时间内某个用户或整个系统能发起的请求数量,防止系统被突发流量冲垮。
为什么需要限流?
想象你的网站突然被一条热搜带火了。正常每秒 100 个请求, suddenly 变成 10 万个。
服务器没有超能力。它要么:
- 全部处理 → 数据库连接耗尽,内存爆掉,全员挂掉
- 全部拒绝 → 用户体验极差,用户以为网站坏了
- 限流 → 只处理你能承受的数量,多出来的排队或返回友好提示
限流的核心目的就三个:保护系统不崩、保证核心用户可用、防止恶意攻击。
限流怎么做?三种常见策略
1. 固定窗口(Fixed Window)
把时间切成一段一段的。比如"每分钟最多 60 次请求"。
第 0-60 秒:允许 60 次
第 60-120 秒:重置,又允许 60 次
简单高效,但有个小问题——临界突刺。比如你在 59 秒时打了 60 次,61 秒又打 60 次,两秒内就 120 次,是正常限制的 2 倍。
2. 滑动窗口(Sliding Window)
固定窗口的升级版。不再用整分钟的边界,而是把时间分成小格子,实时计算最近 N 秒内的请求数。
更平滑,但实现稍复杂,需要存更多数据。
3. 令牌桶(Token Bucket)
这是最优雅的一种。想象一个桶,每秒往里面放 10 个令牌。请求来了就取一个令牌,桶空了就不能请求。
它的好处是允许短暂的突发——如果桶里攒了 100 个令牌,你可以一口气发 100 个请求,只要之后慢下来补上就行。很多 API 都采用这种方式。
限流用在哪里?
API 服务
开放 API 几乎都会限流。比如 Twitter 的 API 限制每分钟 300 次请求,GitHub API 每小时 5000 次。超限就返回 429 Too Many Requests。
数据库
数据库连接数有限,限流可以防止查询请求把连接池打满。
防刷防攻击
登录接口限制每小时 5 次尝试,暴力破解就几乎不可能。爬虫限制每分钟 10 页,恶意抓取成本大增。
微服务间调用
服务 A 调用服务 B,如果 A 突然流量暴增,限流可以防止 B 被拖垮,避免"雪崩效应"。
限流 vs 缓存 vs 降级
这三个经常一起出现,但分工不同:
| 策略 | 作用 | 类比 |
|---|---|---|
| 缓存 | 减少请求打到后端 | 服务员直接端上备好的菜,不用进厨房 |
| 限流 | 控制请求总量 | 餐厅只接待 100 人,多来的只能等 |
| 降级 | 非核心功能先关掉 | 菜品种类从 100 道减到 20 道,但都能做 |
缓存是"少干活",限流是"控制人数",降级是"砍掉功能"。三者配合,系统才能在流量洪峰中存活。
总结
限流不是限制用户体验,而是保护系统整体可用性的必要手段。就像城市道路的限速——不是为了让你慢,而是为了让所有人都不堵死。
好的限流策略应该:
- 分层——用户级、IP 级、接口级,各设上限
- 友好反馈——超限返回 429 状态码,告诉用户"稍后再试"
- 可配置——不同接口不同额度,核心接口给更多配额
下一次你看到 429 Too Many Requests,别抱怨——那是系统在说:“我尽力了,请稍微等一下。”