分布式服务之限流算法
服务限流,顾名思义是对请求过来的流量做限制,当流量超过服务负载能力的一种保护服务的措施。
常见的限流算法,固定窗口、滑动窗口、漏桶和令牌桶算法,以下分别做简要介绍。
限流算法
固定窗口
固定窗口应该是最容易想到的也是最简单的一个方案,通过设置一个计时器,每个计时器时间内允许N次请求过来,超过的拒绝。
假设限流要求1s内最多100次请求。
特点:
-
抗抖动性差
假设1s的前10ms来了100次请求,那么后边1990ms的流量都拒绝掉了。虽然确实满足了限流的要求,但抗抖动差,流量一个抖动就会触发系统限流。
-
两个周期会超出限流值
比如有两秒,前1s的后0.5s有100次请求,后1s的前0.5s有100次请求,那么中间的1s就是200次请求,超过了限流值。这个问题可以采用滑动窗口做优化。
滑动窗口
滑动窗口就是固定窗口的优化,它对固定窗口做了进一步切分,将统计周期的粒度切分得更细,比如 1 分钟的固定窗口,切分为 60 个 1 秒的滑动窗口,然后统计的时间范围随着时间的推移同步后移。
特点:
- 因为窗口被切的更细,统计要求高,对资源的消耗也就更高,不利于系统性能。
- 同时,滑动窗口和固定窗口一样面临抗抖动性差的问题,“漏桶”算法可以进一步改进它们的问题。
漏桶算法
窗口统计算法会导致流量防抖差,漏桶算法可以改进,可以设置一个缓冲地,让服务按自己的速率执行。
特点:
- 增加了一个桶来缓存请求,在流量突增的时候,可以先缓存起来,直到超过桶的容量才触发限流;
- 对出口的流量上限做了限制,使上游流量的抖动不会扩散到下游服务。这两个改进大大提高了系统的抗抖动能力,使漏桶有了流量整形的能力。
但是,漏桶提供流量整形能力有一定的代价,超过漏桶流出速率的请求,需要先在漏桶中排队等待,其中流出速率是漏桶限流的防线,一般会设置得相对保守,可是这样就无法完全利用系统的性能,就增加了请求的排队时间。
令牌桶算法
令牌桶算法的核心是固定“进口”速率,限流器在一个一定容量的桶内,按照一定的速率放入 Token ,然后在处理程序去处理请求的时候,需要拿到 Token 才能处理;如果拿不到,就进行限流。因此,当大量的流量进入时,只要令牌的生成速度大于等于请求被处理的速度,那么此时系统处理能力就是极限的。
特点:
-
令牌是以恒定不变速率产生
-
消费请求的流量可能抖动 速率是不定的,但不会超过令牌生成的速度
漏桶和令牌桶比较:
根据漏桶和令牌桶的特点,我们可以看出,这两种算法都有一个“恒定”的速率和“可变”的速率。
- 令牌桶以“恒定”的速率生产令牌,但是请求获取令牌的速率是“可变”的,桶里只要有令牌就直接发,令牌没了就触发限流;
- 漏桶只要桶非空,就以“恒定”的速率处理请求,但是请求流入桶的速率是“可变”的,只要桶还有容量,就可以流入,桶满了就触发限流。
这里我们也需要注意到,“令牌桶”算法相对于“漏桶”,虽然提高了系统的资源利用率,但是却放弃了一定的流量整形能力,也就是当请求流量突增的时候,上游流量的抖动可能会扩散到下游服务。
参考
- 《深入浅出分布式技术原理》