1、问题
系统的某个接口访问量突然激增,没多久接口崩溃,形成连锁反应,导致整个系统崩溃。
如何应对这种情况呢?
为我们的接口加上“保险丝”,预防这种突发情况,接口压力过大,造成整个系统瘫痪。当接口流量过大时,我们可以通过拒绝访问或等待等机制,即限流。
2、限流常用算法
2.1 漏桶算法
漏桶算法(Leaky Bucket)是网络世界中流量整形(Traffic Shaping)或速率限制(Rate Limiting)时经常使用的一种算法,它的主要目的是控制数据注入到网络的速率,平滑网络上的突发流量。漏桶算法提供了一种机制,通过它,突发流量可以被整形以便为网络提供一个稳定的流量。
漏桶可以看作是一个带有常量服务时间的单服务器队列,如果漏桶(包缓存)溢出,那么数据包会被丢弃。 在网络中,漏桶算法可以控制端口的流量输出速率,平滑网络上的突发流量,实现流量整形,从而为网络提供一个稳定的流量。
如图所示,把请求比作是水,水来了都先放进桶里,并以限定的速度出水,当水来得过猛而出水不够快时就会导致水直接溢出,即拒绝服务。
2.1.1 实现原理
队列接收到准备转发的数据包
队列被调度,得到转发机会,由于队列配置了流量整形,其中的数据包先进入漏桶
根据数据包到达漏桶的速率与漏桶的输出速率关系,确定数据包是否被转发:
如果到达速率 ≤ 输出速率,则漏桶不起作用
如果到达速率 > 输出速率,则考虑漏桶是否能承担瞬间流量
若数据包到达的速率 - 漏桶流出的速率 ≤ 配置的漏桶突发速率,则数据包可被不延时的送出
若数据包到达的速率 - 漏桶流出的速率 > 配置的漏桶突发速率,则多余的数据包被存储到漏桶中
暂存在漏桶中的数据包在不超过漏桶容量的情况下延时发出
若数据包到达的速率 - 漏桶流出的速率 > 配置的漏桶突发速率,且数据包的数量已经超过漏桶的容量,则这些数据包将被丢弃
2.2 令牌桶算法
令牌桶算法是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的一种算法。典型情况下,令牌桶算法用来控制发送到网络上的数据的数目,并允许突发数据的发送。
令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。从原理上看,令牌桶算法和漏桶算法是相反的,一个“进水”,一个是“漏水”。
Google的Guava包中的RateLimiter类就是令牌桶算法的解决方案。
2.2.1 实现原理
令牌桶算法的基本过程:
3、对比
3.1 漏桶算法举例
在某些情况下,漏桶算法不能够有效地使用网络资源,因为漏桶的漏出速率是固定的,所以即使网络中没有发生拥塞,漏桶算法也不能使某一个单独的数据流达到端口速率。因此,漏桶算法对于存在突发特性的流量来说缺乏效率
比如说存在两个系统A、B,公用一个网络,网络带宽为2M, A、B各分得1M,此时通过漏桶算法控制两个系统使用网络的速率,A、B系统使用网络的速率固定最大值为1M,无论A、B系统接受多少流量,但流出的速率都限制在最大1M,当网络中没有发生拥塞,也就是可能出现B系统可能空闲没有使用网络,对应分给B系统的1M带宽是空闲的,而A系统这一时刻接收了5M的流量,由于漏桶限流的存在,A只能使用1M带宽,我们的带宽有2M,此刻我们只能使用1M,也就是达不到带宽的最大速率,另外1M带宽是浪费的,因此不能充分利用,缺乏效率;当然从另一方面来讲也带来了好处,就是隔离性,A系统无论收到多大的流量冲击,对于B系统的无感的,不会因为流量冲击A,而B受到影响.
3.2 令牌桶算法举例
令牌桶算法能够在限制数据的平均传输速率的同时还允许某种程度的突发传输。
比如我们的目标现在是每秒钟处理10个请求,使用漏桶法,我们设置桶的大小为10,流出的速率为0.1s流出一个请求,我们可以达成我们的目标;而使用令牌桶的话,我们会设置每1s向桶中放入10个令牌,请求如果是平稳的,每0.1s过来一个请求,来十个,同样能达到我们的目标,这里所说的某种程度的突发传输是指,比如在一秒内前0.5s请求是平稳的,每0.1s来一个,但在0.6s的时候突发请求同时来个5个请求,此时令牌算法是可以承受这个突发流量的,并且让5个请求成功立刻同时通过,完成了所谓的某种程度的突发传输,而漏桶算法,也可以应对这种突发流量,但不同的是没有让5个请求同时立刻通过,而是缓冲在桶中,然后仍然以固定速率每0.1s通过一个。
3.3 总结
这两种算法,都可以实现流速的控制,1s处理10个请求,多于10个的请求都会被拒绝,但由于漏桶算法流出速率是一定的,所以请求可能会被缓冲在桶中,不能马上得到处理,从而徒增了等待时间,而对于令牌桶算法,没有这种等待时间,有令牌则通过,无令牌则抛弃。
4、应用场景
并不能说明令牌桶一定比漏洞好,它们使用场景不一样。令牌桶可以用来保护自己,主要用来对调用者频率进行限流,为的是让自己不被打垮。所以如果自己本身有处理能力的时候,如果流量突发(实际消费能力强于配置的流量限制),那么实际处理速率可以超过配置的限制。而漏桶算法,这是用来保护他人,也就是保护他所调用的系统。主要场景是,当调用的第三方系统本身没有保护机制,或者有流量限制的时候,我们的调用速度不能超过他的限制,由于我们不能更改第三方系统,所以只有在主调方控制。这个时候,即使流量突发,也必须舍弃。因为消费能力是第三方决定的。
总结起来:如果要让自己的系统不被打垮,用令牌桶。如果保证被别人的系统不被打垮,用漏桶算法。
参考:
https://blog.csdn.net/yin__ren/article/details/102798407
https://www.jianshu.com/p/c6b20845561a
https://blog.p2hp.com/archives/4351
https://www.cnblogs.com/junzi2099/p/14208640.html