一.概述
由于 API 接口无法控制调用方的行为,因此当遇到瞬时请求量激增时,会导致接口占用过多服务器资源,使得其他请求响应速度降低或是超时,更有甚者可能导致服务器宕机。限流(Ratelimiting)指对应用服务的请求进行限制,例如某一接口的请求限制为 100 个每秒,对超过限制的请求则进行快速失败或丢弃。
限流可以应对:
-
热点业务带来的突发请求;
-
调用方 bug 导致的突发请求;
-
恶意攻击请求。
二.限流的算法
2.1固定窗口计算器算法
概念如下:
- 将时间划分成一个窗口
- 在每个窗口内有一次请求就将计数器加一
- 如果计数器超过了限制数量,则本窗口内所有的请求都被丢弃当时间到达下一个窗口时,计数器重置。
固定窗口计算器方法是最简单的方法,但是这个方法会让请求数量为限制的2倍:限制1秒内最多通过5个请求,在第一个窗口的最后半秒内通过了5个请求,在下一个窗口的前半秒内又通过了5个请求,这样看来就是1秒内通过了10个请求。
2.2 滑动窗口计数器方法
概念如下:
- 将时间划分成多个区间
- 在每一个区间内每有一次请求就将技术器加一维持在一个时间窗口内,占用多个区间
- 在每经过一个区间的时间,则抛弃最老的一个区间,并纳入一个新的区间
- 如果当前窗口内区间的请求计数总和超出了限制数量,则本窗口内所有请求都被抛弃
滑动窗口计数器是通过将窗口再细分,并按照时间滑动,这样避免了固定窗口计数器带来的双倍突然请求,但时间区间的精度越高,算法需要的空间容量就越大
2.3 漏桶算法
概念如下:
- 将每个请求视为“水滴”放入“漏桶”中进行存储
- “漏桶”以固定速率向外“漏”出请求来执行,如果空了则停止漏水
- 如果“漏桶”满了则多余的“水滴”则会直接被丢弃
漏桶算法多使用队列实现,服务的请求会保存到队列中,服务的提供方则按照固定的速率从队列中取出请求并执行,过多的请求则放在队列中排队或者直接拒绝。
缺陷:当短时间内有大量的突发请求的时候,此时服务器没有任何负载,每个请求也都得在队列中等待一段时间才能被响应。
2.4 令牌桶算法
概念如下:
- 令牌以固定速率生成
- 生成的令牌放入令牌桶中存放,如果令牌桶满了则多余的令牌会被丢弃,当请求到达的时候会从令牌桶中取出令牌,取到令牌的请求可以执行
- 如果桶空了,那么尝试取令牌的请求会被直接丢弃
令牌桶算法能够将所有的请求平均分布到时间区间内,又能接受服务器能够承受范围内的突发请求,因此是目前使用较为广泛的一种限流算法。
上述的来自于:分布式服务限流实战
三.框架中的限流
Hystrix 中的限流可以使用线程池和信号量来实现。