Sentinel -- FLOW SLOT核心原理篇

时间:2020-11-27 21:33:00 来源:互联网 作者: 神秘的大神 字体:

这个节点是sentinel流控接口,主要承担的作用是限流和预热。还是老套路,在介绍源码之前先介绍一下源码中用到的几个核心原理,这样大家看源码相对轻松一些。

1、核心算法

1.1 漏洞算法和令牌通算法

漏桶可以看作是一个带有常量服务时间的单服务器队列,如果漏桶(包缓存)溢出,那么数据包会被丢弃。 在网络中,漏桶算法可以控制端口的流量输出速率,平滑网络上的突发流量,实现流量整形,从而为网络提供一个稳定的流量。

如图所示,把请求比作是水,水来了都先放进桶里,并以限定的速度出水,当水来得过猛而出水不够快时就会导致水直接溢出,即拒绝服务。

1.2令牌桶算法

令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。从原理上看,令牌桶算法和漏桶算法是相反的,一个“进水”,一个是“漏水”。

1.3预热桶算法

系统在初始化或者长时间处于低利用率下,系统由于所依赖资源的限制,并不能立马达到它正常的服务水平;例如系统依赖的缓存过期导致新的请求会直接请求 db,再比如很多系统使用了连接池,长时间的 idle 情况下连接池只会保持少量的连接,新的请求会重新创建连接,这些都是耗时操作,完成这些操作之后,系统才能到达正常的服务水平。这时候变需要预热桶算法。
 
预热桶算法本质是按照一个 y=mx+b的一个线性函数,将投入令牌桶的时间间隔又大到小的过程。下面是guava源码中的一个函数图。
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源码解读

流控节点整体流程是:先验证流量是否超过阀值,没有的情况下载进入下一个节点。

代码往下跟,最终进入单机限流模式下。
集群限流在sentinel这个组件中个人不推荐,虽然集权能解决如下问题:
  • 假设集群中有 10 台机器,我们给每台机器设置单机限流阈值为 10 qps,理想情况下整个集群的限流阈值就为 100 qps。不过实际情况下路由到每台机器的流量可能会不均匀,会导致总量没有到的情况下某些机器就开始限流。
  • 每台单机实例只关心自己的阈值,对于整个系统的全局阈值大家都漠不关心,当我们希望为某个 api 设置一个总的 qps 时(就跟为 api 设置总的调用次数一样),那这种单机模式的限流就无法满足条件了。
但是,sentinel的集群限流会引入新的服务新的依赖并没有对其进行熔断处理,本来是未来保护系统,如果用集群限流会引入新的风险点。这是个人片面理解仅供参考。
 
接下来看下限流具体如何处理的
四个子类对应四种限流场景:快速失败,预热,排队等待。

2.1直接限流快速失败场景

当前请求数量加上滑动时间窗口统计的前一秒的请求数量大于设定阀值直接失败。

2.2直接限流快速预热场景

初始化场景就不说了类似前面的预热桶的计算方式。最终计算一个函数,稳定的减少往桶里方每个token的时间,最终达到稳定PQS。
校验是否通过
产生令牌