为什么要限流?
由于Web服务无法控制调用方的行为,当遇到请求并发量超过系统的容量阈值,会导致服务器资源耗尽从而导致服务异常或宕机,而且某个服务的请求量突增还会影响到上游的服务,如DB或者是其他的公共服务,导致整个系统瘫痪。
可能导致流量突增的原因有以下几点:
- 热点业务的突发请求(如大型活动)
- 调用方bug导致的请求量倍增
- 恶意攻击的请求
为了对服务进行保护,就需要对请求进行限流。
常见算法
固定窗口计数器算法
算法思路:
- 将时间划分为多个窗口
- 每个窗口内每有一次请求计数器加1
- 如果计数器超过了限制数量,则本窗口内的所有请求都被丢弃,当时间到达下一个窗口时,计数器重置。
特点:原理和实现都比较简单,但是这种算法可能会让通过的请求量为阈值的两倍。比如当阈值是100时,第一个窗口在0-0.5秒期间没有请求,0.5-1.0秒期间有100个请求,然后到了第二个窗口计数器已经重置,在1.0-1.5秒期间有100个请求,这样看来在0.5-1.5秒的1秒内通过了200个请求。
滑动窗口计数器算法
该方法就是对固定窗口计数算法的窗口时间细分更多的区间,并且按照时间在区间上滑动,如下图所示:
算法思路:
- 将时间划分多个区间,维护一个包含多个区间的窗口
- 每个区间内每有一次请求就将该区间的计数器加1
- 每经过一个区间时间,丢弃最老的一个区间,加入最新的一个区间
- 如果当前窗口内区间的请求计数总和超过了限制数量则本窗口内所有新的请求都被丢弃。
特点:
将时间划分为更小单位的区间,按时间滑动,避免了固定窗口计数器会产生双倍请求的问题,但是时间区间的精度越高,算法需要的空间容量就越大。
漏桶算法
算法思路:
- 将每个请求视作“水滴”放入“漏桶”进行存储
- 漏桶以固定的速率(通常是服务的最大容量)向外漏出请求交给服务器执行
- 如果漏桶空了则停止漏水,如果漏桶满了则丢弃新来的请求
特点:通常使用消息队列来实现漏桶。该算法能良好的保证瞬时请求量不会超过阈值,但是当短时间内有大量的突发请求时,即使服务器没有负载,每个请求也都需要在队列中等待一段时间才能被响应。
令牌桶算法
算法思路:
- 令牌以固定速录添加到桶中,如果桶满了直接丢弃
- 请求到达时从桶中取令牌,取到了令牌的请求交给服务器执行
- 如果桶空了,尝试取令牌的请求就会被拒绝
特点:令牌桶算法既能将流量均匀的分布,又能接受服务器承受的容量范围内的突发请求,因此是目前使用比较广泛的一种限流算法。缺点是突发流量时第一个周期会多放过一些请求。
网友评论