正文
系列目录
引子
任何一个系统的运算、存储、网络资源都不是无限的,当系统资源不足以支撑外部超过预期的突发流量时,便应该要有取舍,建立面对超额流量自我保护的机制,这个机制就是微服务中常说的“限流”。
1.流量统计指标
- 每秒事务数(Transactions per Second,TPS):TPS 是衡量信息系统吞吐量的最终标准。“事务”可以理解为一个逻辑上具备原子性的业务操作。
- 每秒请求数(Hits per Second,HPS):HPS 是指每秒从客户端发向服务端的请求数(请将 Hits 理解为 Requests 而不是 Clicks,国内某些翻译把它理解为“每秒点击数”多少有点望文生义的嫌疑)。
- 每秒查询数(Queries per Second,QPS):QPS 是指一台服务器能够响应的查询次数。
目前,主流系统大多倾向使用 HPS 作为首选的限流指标,它是相对容易观察统计的,而且能够在一定程度上反应系统当前以及接下来一段时间的压力。但限流指标并不存在任何必须遵循的权威法则,根据系统的实际需要,哪怕完全不选择基于调用计数的指标都是有可能的。譬如下载、视频、直播等 I/O 密集型系统,往往会把每次请求和响应报文的大小,而不是调用次数作为限流指标,譬如只允许单位时间通过 100MB 的流量。又譬如网络游戏等基于长连接的应用,可能会把登陆用户数作为限流指标,热门的网游往往超过一定用户数就会让你在登陆前排队等候。
2.限流算法
对于具体如何进行限流,也有一些常见常用的设计模式可以参考使用,本节将介绍流量计数器、滑动时间窗、漏桶和令牌桶四种限流设计模式。
2.2.1 固定窗口计数器
固定一个时间段内流量计数到达阈值限流。时间窗口结束清空计数。存在跨窗口流量最多2N流量问题。
2.2.2 滑动窗口计数器
滑动时间窗口模式的限流完全解决了流量计数器的缺陷,可以保证任意时间片段内,只需经过简单的调用计数比较,就能控制住请求次数一定不会超过限流的阈值,在单机限流或者分布式服务单点网关中的限流中很常用。不过,这种限流也有其缺点,它通常只适用于否决式限流,超过阈值的流量就必须强制失败或降级,很难进行阻塞等待处理,也就很难在细粒度上对流量曲线进行整形,起不到削峰填谷的作用。下面笔者继续介绍两种适用于阻塞式限流的限流模式。
2.2.3 漏桶算法
在计算机网络中,专门有一个术语流量整形(Traffic Shaping)用来描述如何限制网络设备的流量突变,使得网络报文以比较均匀的速度向外发送。 流量整形通常都需要用到缓冲区来实现,当报文的发送速度过快时,首先在缓冲区中暂存,然后再在控制算法的调节下均匀地发送这些被缓冲的报文。常用的控制算法有漏桶算法(Leaky Bucket Algorithm)和令牌桶算法(Token Bucket Algorithm)两种,这两种算法的思路截然相反,但达到的效果又是相似的。
漏桶:一个水池,每秒以 X 升速度注水,同时又以 Y 升速度出水。漏桶在代码实现上非常简单,就是一个以请求对象作为元素的先入先出队列(FIFO Queue),队列长度就相当于漏桶的大小,当队列已满时便拒绝新的请求进入。漏桶实现起来很容易,困难在于如何确定漏桶的两个参数:桶的大小和水的流出速率。
2.2.4 令牌桶算法
假设我们要限制系统在 X 秒内最大请求次数不超过 Y,那就每间隔 X/Y 时间就往桶中放一个令牌,当有请求进来时,首先要从桶中取得一个准入的令牌,然后才能进入系统处理。任何时候,一旦请求进入桶中却发现没有令牌可取了,就应该马上失败或进入服务降级逻辑。
2.2.5 分布式限流
前面讨论过的那些限流算法,直接使用在单体架构的集群上是完全可行的,但到了微服务架构下,它们就最多只能应用于集群最入口处的网关上,对整个服务集群进行流量控制,而无法细粒度地管理流量在内部微服务节点中的流转情况。所以,我们把前面介绍的限流模式都统称为单机限流,把能够精细控制分布式集群中每个服务消耗量的限流算法称为分布式限流。例如:阿里爸爸开源的面向分布式服务架构的流量控制框架Sentinel,这里不展开讨论。
2.2.6 总结
4种常见限流算法和常见工具的对比如下表:
算法名称 | 描述 | 优点 | 缺点 | 适合场景 |
---|---|---|---|---|
固定窗口计数器 |
固定一个时间段内流量计数到达阈值限流。 | 简单易实现,性能高 | 跨窗口瞬时流量,最大可以达到阈值的2倍 | 简单粗暴,适合临时方案。 |
滑动窗口计数器 |
窗口划分为多个更细粒度的单元,每次窗口向右移动一个单元, 即时间分段+时间滑动统计到达阈值限制。 |
精细化限流 | 峰值流量被丢弃,流量不平滑。 | 适合应对有少量突增流量场景。 |
漏桶算法 |
配置一个FIFO的队列使用以达到允许限流的作用。捅满丢弃流 量,固定速率流出流量。 |
流量平滑,系统稳定 |
|
适合强制平滑限流场景。宽进严出模式,是一个通用性方案。 |
令牌桶算法 |
以固定的速率产生令牌放入一个固定容量为n的桶中,当请求到 达时尝试从桶中获取令牌。获取不到令牌,丢弃流量。 |
允许瞬时大流量 |
|
适合系统经常有突增流量,并尽可能的压榨服务的性能。 |