服务治理之限流

Posted by Mr.Cai on July 30, 2018

0x01 限流的应用场景

  • 单实例限流:防止单实例被突如其来的流量压垮,导致调用链的雪崩效应,保护系统的可用性,而做出的自我保护策略。
  • 服务限流:对于一些平台,需要对业务方的接口调用做隔离,防止因业务方的bug产生的流量压垮平台的服务接口造成的服务不可用,而影响到其他的业务方。

0x02 流量的定义

  • 网络流量
  • TPS
  • hits per second

0x03 限流种类

  • 服务方限流
  • 调用方限流

0x04 限流算法

假设1s内可以处理3000个事务。

  • 固定窗口:维护一个计数器,如果在窗口时间单元内且不超过3000,则允许请求。存在的问题可能是流量高峰集中在第一秒内的最后10ms内,第二秒的最初10ms内,这样有可能在20ms中要处理6000个事务。
  • 滑动窗口:细分时间单元,划分多个小窗口,基于时间滑动,在总窗口内的请求总数不能超过3000,可以解决固定窗口的问题。但是缺点是无法解决小窗口内的请求集中的问题,如果10ms内涌入3000,可能造成服务被流量压垮。
    窗口划分太细容易导致正常的请求被误限流,窗口太粗,导致限流无法起到很好的作用。所以一般的平滑策略是多层次限流,设置多条限流策略使用滑动窗口限制请求速率,使用细粒度固定窗口防止请求集中的问题。为了优化窗口算法的问题,出现了漏桶算法和令牌桶算法。
  • 令牌桶算法:有一个固定容量的桶,桶里存放着令牌(token)。桶一开始是空的,token以一个固定的速率r往桶里填充(本次和上次请求时间戳计算),直到达到桶的容量,多余的令牌将会被丢弃。每当一个请求过来时,就会尝试从桶里移除一个令牌,如果没有令牌的话,请求无法通过,优点是对突发的流量可以有适当的弹性,但是要注意令牌桶的总量不能超过服务的处理能力。
  • 漏桶算法:有一个固定容量的桶,有水流进来,也有水流出去。对于流进来的水来说,我们无法预计一共有多少水会流进来,也无法预计水流的速度。但是对于流出去的水来说,这个桶可以固定水流出的速率(本次和上次请求时间戳计算)。而且,当桶满了之后,多余的水将会溢出,优点是即便突发流量来临,也会保持一定的速率去处理,大量的流量不会压垮服务。

0x05 分布式限流

一般需要引用第三方缓存,需要考虑缓存的访问性能、数据的一致性、缓存访问超时问题。

实施层面

  • 接入层:在边缘服务上来做,这也是一个缺点,但是如果做平台,API网关肯定是要的。
  • RPC层:也是一个边缘服务,限流服务。
  • 业务代码层:封装SDK,在调用方做限流,缺点很明显,不安全。

0x06 限流策略

  • 拒绝策略:对RT要求高的服务接口。
  • 排队策略:耗时长的服务接口。

0x07 限流规则

  • 时间粒度:时间窗口的大小、令牌的投放速率、漏桶的消费速率。对于突发流量高的,时间粒度要小一点,对于突发流量少的,时间窗口大一点。
  • 接口粒度:集群访问粒度、服务访问粒度、服务接口访问粒度。
  • 最大限流值:不大于压测的TPS并且不小于业务的预期流量,针对监控数据做一些适当调整。