Sentinel之滑动时间窗口设计(一)

本文基于:1.3.0-GA版本

这里截取官网的一张图:

总体框架

Slot是从第一个往后一个个传递的,当数据到了StatisticSlot时,就开始进行统计了。
后面的所有的Slot都依赖这个统计进行校验。

StatisticSlot就是根据滑动窗口进行数据统计的,下面开始讲解。

一、包结构

如图:

image.png

红框内既是本文要分析的内容。

1、base包的内容主要就是滑动窗口的设计及多线程计数统计
2、metic包主要是指标的统计及指标数据的集合封装
3、StatisticSlot就是统计核心入口了,主要统计了正常情况、发生BlockException、其他异常的统计数据
4、StatisticSlotCallbackRegistry回调注册器,后续热点参数限流会涉及到

二、Metric及ArrayMetric

Metric

Metric是一个接口,用来统计各项指标的一个入口,如:success(成功数)、exception(异常数)、block(阻塞数)、pass(请求数)、rt(响应时间);并定义了这些指标的增加方法。

ArrayMetric

ArrayMetric是Metric的实现类,ArrayMetric实现了Metric定义的所有的方法;
注意ArrayMeric的构造方法,通过调用查询,可以发现StatisticNode类中定义的,如:

public class StatisticNode implements Node {

    private transient volatile Metric rollingCounterInSecond = new ArrayMetric(1000 / SampleCountProperty.SAMPLE_COUNT,
        IntervalProperty.INTERVAL);

    /**
     * Holds statistics of the recent 60 seconds. The windowLengthInMs is deliberately set to 1000 milliseconds,
     * meaning each bucket per second, in this way we can get accurate statistics of each second.
     */
    private transient Metric rollingCounterInMinute = new ArrayMetric(1000, 60);

    //下面代码省略
}
    /**
    * 数据保存到地方
    */
     private final MetricsLeapArray data;
     /**
     * Constructor
     *
     * @param windowLengthInMs a single window bucket's time length in milliseconds.
     * @param intervalInSec    the total time span of this {@link ArrayMetric} in seconds.
     */
    public ArrayMetric(int windowLengthInMs, int intervalInSec) {
        this.data = new MetricsLeapArray(windowLengthInMs, intervalInSec);
    }

然后通过MetricsLeapArray的构造函数,构造滑动时间窗口:
这里通过注释的解释就能发现了

windowLengthInMs:一个单口滑动时间窗口的大小,单位是毫秒
intervalInSec:窗口的区间大小,单位秒

MetricsLeapArray又调用父类的LeapArray的构造方法进行构造。

三、LeapArray及WindowWrap

LeapArray

    //单口滑动时间窗口的大小,单位是毫秒
    protected int windowLengthInMs;
    //滑动时间窗口个数
    protected int sampleCount;
    //统计时间区间
    protected int intervalInMs;
     
    /**
      保存统计数据的地方,数组
    */
    protected final AtomicReferenceArray<WindowWrap<T>> array;

//构造函数
  public LeapArray(int windowLengthInMs, int intervalInSec) {
        this.windowLengthInMs = windowLengthInMs;
        //因为intervalInSec单位是秒,所以乘以1000
        this.intervalInMs = intervalInSec * 1000;
        this.sampleCount = intervalInMs / windowLengthInMs;

        this.array = new AtomicReferenceArray<WindowWrap<T>>(sampleCount);
    }

可以看到窗口的统计数据被被包装到WindowWrap了

WindowWrap

    /**
     * a single window bucket's time length in milliseconds.
     */
    private final long windowLengthInMs;

    /**
     * Start time of the window in milliseconds.
     */
    private long windowStart;

    /**
     * Statistic value.
     */
    private T value; 

WindowWrap是一个对象,真正的数据被保存到泛型T的value中,在这里使用的是MetricBucket对象。

MetricBucket

private final LongAdder pass = new LongAdder();
private final LongAdder block = new LongAdder();
private final LongAdder exception = new LongAdder();
private final LongAdder rt = new LongAdder();
private final LongAdder success = new LongAdder();

这里使用的LongAdder,LongAdder是JDK8新增的一个类,和AtomicLong类似,但是LongAdder支持在多线程下有更高的吞吐量。

四、调用链

通过分析上述关系,可以发现完整的流程如下:


调用链

具体分析

1、StatisticSolt是一个统计插槽,也是我们调用链入口:

public class StatisticSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, Object... args)
        throws Throwable {
        try {
            fireEntry(context, resourceWrapper, node, count, args);
            node.increaseThreadNum();
            
             //这里开始调用增加统计次数
            node.addPassRequest();

            if (context.getCurEntry().getOriginNode() != null) {
                context.getCurEntry().getOriginNode().increaseThreadNum();
                context.getCurEntry().getOriginNode().addPassRequest();
            }
//以下代码省略
//......
}

2、通过DefaultNote调用父类StatisticNode的addPassRequest方法
3、StatisticNode创建了两个统计Metric:rollingCounterInSecond、rollingCounterInMinute,进行调用ArrayMetric的addPass方法
4、构建了时间窗口MetricsLeapArray,并调用:

@Override
public void addPass() {
    WindowWrap<MetricBucket> wrap = data.currentWindow();
    wrap.value().addPass();
}

从LeadArray数组中获取到当前时间的窗口包装器,
获取当前时间的时间窗口方法currentWindow,下一节详细介绍:https://www.jianshu.com/p/05677381e155
5、在该时间包装器对数据MetricBucket进行指标的操作

   public void addPass() {
        pass.add(1L);
    }

五、总结

1、本文分析整个滑动时间窗口的构建过程及详细的调用链。
2、StatisticSlot是sentinel统计的核心,后续的流控,降级等都是根据此阶段的统计数据进行的。
3、本文目前还没有介绍滑动时间窗口的具体算法,请关注下一篇文章。
4、统计指标数据是根据LongAdder数据结构进行各项统计的,主要原理就是利用分段写入,减少竞争。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容