服务化架构-服务的限流

1. 什么是限流

顾名思义,限流就是限制请求量,当用户请求量达到设定的阈值之后,对超出部分的请求进行拒绝或者延时处理。

2.为什么要限流

限流是服务提供方进行自我保护的一种手段。如果对用户请求量不做限制,那么过多的请求很有可能会将服务器有限的资源消耗殆尽,最终导致服务器宕机,进而引发雪崩。所以对于高可用的系统来讲,限流是一种必不可少的手段。

3. 限流算法

3.1 令牌桶(Token bucket)

令牌桶算法的基本过程如下:

  1. 每秒会有 r 个令牌放入桶中,或者说,每过 1/r 秒桶中增加一个令牌;
  2. 桶中最多存放 b 个令牌,如果桶满了,新放入的令牌会被丢弃;
  3. 当一个 n 字节的数据包到达时,消耗 n 个令牌,然后发送该数据包;
  4. 如果桶中可用令牌小于 n,则该数据包将被缓存或丢弃;

令牌桶算法的实现,可以借助于Google guava的RateLimiter实现,使用SmoothBursty模式。具体实现将在后面的blog中进行详细说明。

3.2 漏桶(Leaky bucket)

漏桶算法强制一个常量的输出速率而不管输入数据流的突发性,当输入空闲时,该算法不执行任何动作.就像用一个底部开了个洞的漏桶接水一样,水进入到漏桶里,桶里的水通过下面的孔以固定的速率流出,当水流入速度过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率.如下图所示:

漏桶的实现,可以使用Guava RateLimiter的SmoothWarmingUp模式实现。

3.3 令牌桶与漏桶算法的比较

令牌桶算法能够允许一定程度的流量突增,要令牌桶中存在令牌,那么就允许突发地传输数据直到达到用户配置的上限,因此它适合于具有突发特性的流量。
漏桶算法能够强行限制数据的传输速率,因此更适合进行平滑限流的应用场景,比如限制下载速率。

4. 限流方式

4.1 单机限流

单机限流一般使用在对硬件资源进行保护的场景中,避免服务器过载而宕机,引发进一步的雪崩。比如对访问量进行限流。有同学可能会问了,我评估一个集群总体的阈值,用集群限流不也可以吗?这里面存在的隐患是,如果负载均衡策略不够均衡,可能会导致部分服务器存在热点,那么那些流量仍然有可能将这台热点服务器打挂掉,从而引发雪崩。

4.2 集群限流

集群限流的方式一般会使用在某些外部资源存在访问限制的情况下,比如依赖的第三方系统限制了请求的访问量,那么上游的系统就需要在请求第三方系统前进行全局的限流,避免对方因过载而拒绝服务。比如说抓取。