0
点赞
收藏
分享

微信扫一扫

sentinel滑动时间窗口算法统计通过请求数量细节

笙烛 2022-04-02 阅读 100
微服务

问题描述

昨天写的笔记中,最后我留了一个疑问,疑问是这样的:
假如:在0-500ms之间有4次请求,500-1000ms之间有4个请求;在1000ms - 1500ms之间请求次数为0,1600ms的时候,有三个请求进来,此时
在这里插入图片描述

在进行判断的时候,会把第二个窗口进行reset:也就变成了这样:
在这里插入图片描述

我的疑问是:此时在统计qps的时候,如果还是直接把两个窗口的请求次数累加到一起,那就统计的不是前1S之内的请求数了;、
今天翻了下源码,发现针对这个场景的源码了:

源码

com.alibaba.csp.sentinel.node.StatisticNode#successQps

这个类中,是获取相关统计指标的收口类,就是说,不管是限流、降级还是其他场景需要获取相关的qps指标,都需要通过这个类实现,所以我们找其中的一个方法看下实现源码:

public double successQps() {
    return rollingCounterInSecond.success() / rollingCounterInSecond.getWindowIntervalInSec();
}

要统计qps,当然是同success的数量 / 1S
rollingCounterInSecond.getWindowIntervalInSec() 这个不贴代码了,里面就是用1000ms / 1000ms;这个计算方法的意思是说:如果在初始化时,预设的时间窗口是1000ms,那就除以1000ms 得到对应的秒,得到1S,也就是说当前窗口中统计的是1S内的请求数量
关键要看的是rollingCounterInSecond.success()

public long success() {
    data.currentWindow();
    long success = 0;

    List<MetricBucket> list = data.values();
    for (MetricBucket window : list) {
        success += window.success();
    }
    return success;
}

这个方法大致的意思:就是说获取到当前所有的窗口,把窗口中success的数量累计起来,关键的代码,在data.values();

public List<T> values(long timeMillis) {
    if (timeMillis < 0) {
        return new ArrayList<T>();
    }
    int size = array.length();
    List<T> result = new ArrayList<T>(size);

    for (int i = 0; i < size; i++) {
        WindowWrap<T> windowWrap = array.get(i);
        /**
         * 在统计近1S的通过请求数量时,有一个很重要的判断,就是这里:
         *  会判断当前时间 - 窗口的起始时间,是否大于 1000ms,如果大于1000ms 就不处理
         */
        if (windowWrap == null || isWindowDeprecated(timeMillis, windowWrap)) {
            continue;
        }
        result.add(windowWrap.value());
    }
    return result;
}

//当前时间 - 窗口的起始时间,如果大于1000ms,就不统计 intervalInMs:是我们初始化时,指定的统计时间,sentinel中默认是1000ms
public boolean isWindowDeprecated(long time, WindowWrap<T> windowWrap) {
    return time - windowWrap.windowStart() > intervalInMs;
}

这段代码可以看到,会依次遍历每个窗口,如果当前时间 - 窗口的起始时间,大于qps统计的时间1000ms,就不统计,那上面的场景,就可以解释了:
在这里插入图片描述

窗口0在统计的时候,由于1600ms - 0ms > 1000ms 所以0-500ms之间的4次请求是不会被统计的
窗口1在统计的时候,1600 - 1500ms < 1000ms ,所以会被统计进去

结论

所以:结论就是,虽然这种场景也是有两个窗口,但是sentinel在统计的时候,会过滤当前时间和窗口起始时间在1000ms之内的所有窗口,统计对应的请求次数

举报

相关推荐

0 条评论