流量限流
在高并发场景下,需要处理大量请求时,
我们可以对这些请求请求进行限流,以防止自身服务由于资源耗尽而停止服务。
| 阈值 | 限流条件,比如设置QPS,每秒允许多少请求 |
| 拒绝策略 | 直接拒绝 / 进入等待队列 |
一、 固定窗口限流算法
维护一个计数器,将每个时间段当做一个窗口,计数器去记录窗口的接收请求次数。
1. 假设:
每秒为一个窗口,阈值为每秒10个请求(QPS:10)。
- 第 1 秒进入 9 个请求,计数器为 9,未到阈值,正常执行\color{green}{未到阈值,正常执行}未到阈值,正常执行。
- 第 2.4 秒进入 6 个请求,计数器为 6,未到阈值,正常执行\color{green}{未到阈值,正常执行}未到阈值,正常执行。
- 第 2.7 秒进入 4 个请求,计数器为 10,未到阈值,正常执行\color{green}{未到阈值,正常执行}未到阈值,正常执行。
- 第 2.9 秒进入 1 个请求,计数器为 11,达到阈值,执行拒绝策略\color{red}{达到阈值,执行拒绝策略}达到阈值,执行拒绝策略。

2. 缺点:
虽然我们规定每秒只允许10个请求执行。
但是在时间窗口切换的时候,可以突破这个限制。

我们可以看到第一窗口7个请求、第二窗口9个请求,单独来看没有问题。
但是看500ms到1500ms区间,一秒内已经有16个请求了,这已经突破我们QPS10的规则了。
二. 滑动窗口限流算法
滑动窗口限流解决固定窗口临界值的问题。
- 将时间分成n个格子,每个小格子记录每段时间的请求次数。
- 然后有一个根据时间滑动的窗口,这个滑动窗口去计算格子的请求总数。
1. 比如QPS为10的场景
- 100ms为一个格子;
- 滑动窗口大小为1000ms(1秒),可以容纳10个100ms的格子;
- 滑动窗口根据时间滑动时,计算窗口内10个格子的请求总数。
- 请求总数不超过10,正常执行\color{green}{不超过10,正常执行}不超过10,正常执行。
- 请求总数超过10,拒绝执行\color{red}{超过10,拒绝执行}超过10,拒绝执行。
小格子划分越多,那么滑动窗口的滚动就越平滑,限流的统计就会越精确。
2. 缺点:
解决了固定窗口的临界问题。
但是限流后,请求都会直接被拒绝。对于某些场景下对用户体验并不是很好。
三、漏桶算法
解决了限流后一些请求会被直接拒绝的问题。
- 添加一个漏桶(队列)
- 先将请求放入漏桶中
- 再按固定速度(QPS)去执行这些请求。
- 当然漏桶也是有上限的,满了依然会直接拒绝。
四、令牌桶算法
有时候面对突发流量的时,我们希望提升处理效率,我们可以使用令牌桶算法。
令牌桶算法的桶里不再存请求,而是存令牌。
- 令牌管理员根据QPS,定速往令牌桶里放令牌。
- 如果令牌桶满了,丢弃令牌。
- 接收请求时,会先去令牌桶取令牌。
- 如果取到令牌,就处理请求;
- 如果取不到令牌,则拒绝请求。
1. 为什么说可以处理突发流量?
- 上一秒用不完令牌,可以留到下一秒使用,这就可以处理一些突发流量。
- 当令牌用完时,就只能等令牌管理员根据QPS放令牌了。
假设依然不满足突发流量需求:
- 可以在令牌桶设置阈值;
- 当令牌桶剩余令牌 >= 阈值(表示这是正常流量),保持QPS速度;
- 当令牌桶剩余令牌 < 阈值(表示这是突发流量),提升QPS速度(提升令牌发放速度)
可以按照自己的需求去设置条件、计算最大QPS。
2. 总结
- QPS决定了令牌管理员放令牌的速度;
- 令牌桶大小决定了处理突发流量的上限。
3. 漏桶算法 和 令牌桶算法 的异同
- 相同:
- 都是通过桶,提高处理上限。
- 不同:
- 漏桶的桶是用于增加等待队列,固定速度。
- 令牌桶的桶是用于处理突发流量上限。
4.令牌桶实现框架
- Guava的RateLimiter限流组件
85万+

被折叠的 条评论
为什么被折叠?



