常用的限流框架都在这里了!
作者:fredalxin地址:https://fredal.xin/netflix-concuurency-limits 作为应对高并发的手段之一,限流并不是一个新鲜的话题了。从Guava的Ratelimiter到Hystrix,以及Sentinel都可作为限流的工具。 自适应限流 一般的限流常常需要指定一个固定值(qps)作为限流开关的阈值,这个值一是靠经验判断,二是靠通过大量的测试数据得出。但这个阈值,在流量激增、系统自动伸缩或者某某commit了一段有毒代码后就有可能变得不那么合适了。并且一般业务方也不太能够正确评估自己的容量,去设置一个合适的限流阈值。而此时自适应限流就是解决这样的问题的,限流阈值不需要手动指定,也不需要去预估系统的容量,并且阈值能够随着系统相关指标变化而变化。自适应限流算法借鉴了TCP拥塞算法,根据各种指标预估限流的阈值,并且不断调整。大致获得的效果如下: 从图上可以看到,首先以一个降低的初始并发值发送请求,同时通过增大限流窗口来探测系统更高的并发性。而一旦延迟增加到一定程度了,又会退回到较小的限流窗口。循环往复持续探测并发极限,从而产生类似锯齿状的时间关系函数。 TCP Vegas vegas是一种主动调整cwnd的拥塞控制算法,主要是设置两个阈值alpha 和 beta,然后通过计算目标速率和实际速率的差diff,再比较差diff与alpha和beta的关系,对cwnd进行调节。伪代码如下:diff = cwnd*(1-baseRTT/RTT)if (diff < alpha)set: cwnd = cwnd + 1else if (diff >= beta)set: cwnd = cwnd - 1elseset: cwnd = cwnd其中baseRTT指的是测量的最小往返时间,RTT指的是当前测量的往返时间,cwnd指的是当前的TCP窗口大小。通常在tcp中alpha会被设置成2-3,beta会被设置成4-6。这样子,cwnd就保持在了一个平衡的状态。 netflix-concuurency-limits concuurency-limits是netflix推出的自适应限流组件,借鉴了TCP相关拥塞控制算法,主要是根据请求延时,及其直接影响到的排队长度来进行限流窗口的动态调整。alpha , beta & threshold vegas算法实现在了VegasLimit类中。先看一下初始化相关代码:private int initialLimit = 20;private int maxConcurrency = 1000;private MetricRegistry registry = EmptyMetricRegistry.INSTANCE;private double smoothing = 1.0; private Function alphaFunc = (limit) -> 3 LOG10.apply(limit.intValue());private Function betaFunc = (limit) -> 6 LOG10.apply(limit.intValue());private Function thresholdFunc = (limit) -> LOG10.apply(limit.intValue());private Function increaseFunc = (limit) -> limit + LOG10.apply(limit.intValue());private Function decreaseFunc = (limit) -> limit - LOG10.apply(limit.intValue());这里首先定义了一个初始化值initialLimit为20,以及极大值maxConcurrency1000。其次是三个 阈值函数alphaFunc,betaFunc以及thresholdFunc。最后是两个增减函数increaseFunc和decreaseFunc。函数都是基于当前的并发值limit做运算的。alphaFunc可类比vegas算法中的alpha,此处的实现是3log limit。limit值从初始20增加到极大1000时候,相应的alpha从3.9增加到了9。betaFunc则可类比为vegas算法中的beta,此处的实现是6log limit。limit值从初始20增加到极大1000时候,相应的alpha从7.8增加到了18。thresholdFunc算是新增的一个函数,表示一个较为初始的阈值,小于这个值的时候limit会采取激进一些的增量算法。这里的实现是1倍的log li