Sentinel滑动时间窗限流算法

Sentinel系列文章

Sentinel熔断限流器工作原理

Sentinel云原生K8S部署实战

Sentinel核心源码解析

时间窗限流算法

如图 
10-20这个时间窗内请求数量是60小于阈值100,这60个请求均可以通过
30-40这个时间窗请求数量是120大于阈值100,其中有20个请求不能通过
复制代码

弊端

10t到16t 10个请求
16t-20t 50个请求
20t-26t 60个请求
26t到30t 20个请求

16t到26t 有了110个请求 超过了阈值 
但这种固定时间窗口算法就不会做限制
不能做到任意时间段内做限流
复制代码

滑动时间窗口

从黄线位置往前推一个时间窗口
看该时间窗窗口内请求数量是否大于阈值
如果大于阈值 该点的请求被拦截
小于阈值 则允许访问
复制代码

这种情况有8个请求不能通过

滑动时间窗口实现了在任意时间段内请求数量都不能超过阈值

但它也带来了新的问题 "重复统计 浪费系统资源"
复制代码

分析点1和分析点2对应的2个时间窗有重叠的统计的部分
复制代码

滑动时间窗口算法改进

如图每个时间窗100t、分成4段 每段25t 每一段对应一个统计数组元素
比如100-125这一段对应 a0 这个数组元素 记录了100-125这单位时间窗内的请求数量

上图棕色线在130的位置 属于125t-150t 这个单位时间窗口 对应数组a1元素
如果请求属于125t-150t这一窗口 统计的请求量都会加到该窗口对应的a1中
复制代码

判断180t这点的请求是否可以通过

计算175t-180t之间的请求量 该时间窗对应a3
则获取a0的统计值+a1的统计值+a2的统计值+ (175t到180t之间的请求量)
看是否超过了阈值100
如果超过则不能通过
如果没有超过则可以通过
复制代码

滑动时间窗口源码解析

  • 对数据的统计
  • 对统计数据的使用

分析这个方法

ArrayMetric

LeapArray

WindowWrap样本窗口实例 范型T为MetricBucket

windowLengthInMs 样本窗口长度
windowStart 样本窗口的起始时间戳
value 当前样本窗口的统计数据 其类型为MetricBucket
复制代码

MetricBucket

MetricEvent数据统计的维度

统计这个时间窗口内 通过请求量、拦截请求量、异常请求量、成功请求量等6个维度的数据 放在LongAddr数组中
复制代码

获取当前时间点所在的样本窗口

计算当前时间所在的样本窗口id

获取当前时间窗的开始时间

1、首先计算27t位于哪个时间窗:27/10=2

下标是0 落在下标为2的位置

2、计算27t这点的请求统计量累计在哪个LeapArray元素中

2%4=2 即a2的位置

3、获取27t所在窗口的开始时间

27t-27%10=20t
复制代码

替换掉老的时间窗口

对象本身没变
复制代码

将当前窗口的请求数据添加到当前样本窗口的统计数据中

通过维度数据

对统计数据如何使用

流控快速失败

以前的加上现在的
复制代码

获取之前统计好的数据

遍历数据将pass维度的数据取出来 求和
复制代码

将当前遍历的样本窗口统计数据记录到result中
复制代码

过时判断

当前时间-窗口起始时间 比时间窗还大 那就是过时了
复制代码