这个节点是sentinel流控接口,主要承担的作用是限流和预热。还是老套路,在介绍源码之前先介绍一下源码中用到的几个核心原理,这样大家看源码相对轻松一些。
1、核心算法
1.1 漏洞算法和令牌通算法
漏桶可以看作是一个带有常量服务时间的单服务器队列,如果漏桶(包缓存)溢出,那么数据包会被丢弃。 在网络中,漏桶算法可以控制端口的流量输出速率,平滑网络上的突发流量,实现流量整形,从而为网络提供一个稳定的流量。
如图所示,把请求比作是水,水来了都先放进桶里,并以限定的速度出水,当水来得过猛而出水不够快时就会导致水直接溢出,即拒绝服务。
1.2令牌桶算法
1.3预热桶算法
throttling
|
cold + | /
interval | | /.
| | / .
| |/ .
| + . ← "f(storedPermits)"
| /| .
| / | .
| / | .
stable +----------/ | . ← "warmup period"
interval | . | . is the area of the trapezoid between thresholdPermits and maxPermits
| . | .
| . | .
0 +----------+---|---+--------------→ storedPermits
0 thresholdPermits maxPermits
我们可以定义一个冷却因子(coldFactor) ,令系统处于最冷的状态下获取一个令牌的时长 coldInterval = stableInterval * coldFactor
;「预热桶」从最冷状态到完成预热进入稳定期有个转折点,到达这个转折点时的令牌数量我们用 thresholdPermits 表示;这样,我们就获得了一个获取(一个)令牌的时长随着令牌数量变化的连续函数 f(storedPermits) :
1) 0 <= storedPermits <= thresholdPermits 时;f(storedPermits) = stableInterval; // 常数函数,函数值始终为 stableInterval ;
2) thresholdPermits <= storedPermits <= maxPermits 时,f(storedPermits) = (coldInterval - stableInterval) * storedPermits / (maxPermits -thresholdPermits); // 正比例函数,比例常数为 (coldInterval - stableInterval) / (maxPermits - thresholdPermits) ;
在上面这张图中,我们画一条与 x 轴垂直的线 n,这条线与函数曲线的交点的纵坐标当前 storedPermits 数量下获取单个令牌所需的时间;
当我们从右向左移动 n 时,表示系统接收到请求,令牌正在被消耗,假设系统连续接收到 k 个请求,获取对应令牌所需要的时间为:t = f(maxPermits) + f(maxPermits - 1) + f(maxPermits - 2) + ... + f(maxPermits - k),通过微积分的知识可以看出来这是在求函数 f 在 maxPermits - k 到 maxPermits 区间的定积分,可以用这个区间的函数图形的面积表示。也就是说图中梯形的面积为我们的预热时间。图中矩形的面积为预热时间的一半。网上及guava源码出的解释:英文冷却因子是3,然后code inteval 到 stable inteval的值是stable inteval到0值的2倍所以预热面积也是2倍的关系。具体情况如下图:
ps:个人理解这里的解释欠妥,如下图如果①和②是二倍的关系还可以理解。这是个人理解欢迎大家给出合理解释。
2、FLOW SLOT源码解读
流控节点整体流程是:先验证流量是否超过阀值,没有的情况下载进入下一个节点。
- 假设集群中有 10 台机器,我们给每台机器设置单机限流阈值为 10 qps,理想情况下整个集群的限流阈值就为 100 qps。不过实际情况下路由到每台机器的流量可能会不均匀,会导致总量没有到的情况下某些机器就开始限流。
- 每台单机实例只关心自己的阈值,对于整个系统的全局阈值大家都漠不关心,当我们希望为某个 api 设置一个总的 qps 时(就跟为 api 设置总的调用次数一样),那这种单机模式的限流就无法满足条件了。