1. 什么是限流
顾名思义,限流就是限制请求量,当用户请求量达到设定的阈值之后,对超出部分的请求进行拒绝或者延时处理。
2.为什么要限流
限流是服务提供方进行自我保护的一种手段。如果对用户请求量不做限制,那么过多的请求很有可能会将服务器有限的资源消耗殆尽,最终导致服务器宕机,进而引发雪崩。所以对于高可用的系统来讲,限流是一种必不可少的手段。
3. 限流算法
3.1 令牌桶(Token bucket)
令牌桶算法的基本过程如下:
- 每秒会有 r 个令牌放入桶中,或者说,每过 1/r 秒桶中增加一个令牌;
- 桶中最多存放 b 个令牌,如果桶满了,新放入的令牌会被丢弃;
- 当一个 n 字节的数据包到达时,消耗 n 个令牌,然后发送该数据包;
- 如果桶中可用令牌小于 n,则该数据包将被缓存或丢弃;
令牌桶算法的实现,可以借助于Google guava的RateLimiter实现,使用SmoothBursty模式。具体实现将在后面的blog中进行详细说明。
3.2 漏桶(Leaky bucket)
漏桶算法强制一个常量的输出速率而不管输入数据流的突发性,当输入空闲时,该算法不执行任何动作.就像用一个底部开了个洞的漏桶接水一样,水进入到漏桶里,桶里的水通过下面的孔以固定的速率流出,当水流入速度过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率.如下图所示:
漏桶的实现,可以使用Guava RateLimiter的SmoothWarmingUp模式实现。
3.3 令牌桶与漏桶算法的比较
令牌桶算法能够允许一定程度的流量突增,要令牌桶中存在令牌,那么就允许突发地传输数据直到达到用户配置的上限,因此它适合于具有突发特性的流量。
漏桶算法能够强行限制数据的传输速率,因此更适合进行平滑限流的应用场景,比如限制下载速率。
4. 限流方式
4.1 单机限流
单机限流一般使用在对硬件资源进行保护的场景中,避免服务器过载而宕机,引发进一步的雪崩。比如对访问量进行限流。有同学可能会问了,我评估一个集群总体的阈值,用集群限流不也可以吗?这里面存在的隐患是,如果负载均衡策略不够均衡,可能会导致部分服务器存在热点,那么那些流量仍然有可能将这台热点服务器打挂掉,从而引发雪崩。
4.2 集群限流
集群限流的方式一般会使用在某些外部资源存在访问限制的情况下,比如依赖的第三方系统限制了请求的访问量,那么上游的系统就需要在请求第三方系统前进行全局的限流,避免对方因过载而拒绝服务。比如说抓取。