sentinel流量统计核心代码-滑动窗口

    /**
     * Get the window at current timestamp.
     *
     * @return the window at current timestamp
     */
    public WindowWrap<T> currentWindow() {
        return currentWindow(TimeUtil.currentTimeMillis());
    }

       /**
     * Get window at provided timestamp.
     *
     * @param time a valid timestamp
     * @return the window at provided timestamp
     */
    public WindowWrap<T> currentWindow(long time) {
        // 获取当前毫秒对应到window length的一个id
        long timeId = time / windowLengthInMs;
        // Calculate current index.
        // 获取这个id对应到滚动数组中的具体index
        // 通过mod操作完成了数组的滚动
        int idx = (int)(timeId % array.length());

        // Cut the time to current window start.
        // 计算出这个window对应的开始时间戳
        time = time - time % windowLengthInMs;

        // 自旋循环开始
        while (true) {
            // 获取index对应的窗口
            WindowWrap<T> old = array.get(idx);
            if (old == null) {
                // 如果是null, 说明出于滚动窗口初始化阶段
                // 创建一个新的窗口,通过调用newEmptyBucket来获取新的统计桶
                WindowWrap<T> window = new WindowWrap<T>(windowLengthInMs, time, newEmptyBucket());
                // CAS 设置 AtomicReferenceArray里面对应的元素
                if (array.compareAndSet(idx, null, window)) {
                    // 如果设置成功就返回当前的window
                    return window;
                } else {
                    // 如果不成功调用 线程让步
                    // 进入下一次自旋循环
                    Thread.yield();
                }
            } else if (time == old.windowStart()) {
                // 如果开始时间与现存的窗口的开始时间一致
                // 表明请求时间戳与现存的窗口匹配,因此直接返回
                return old;
            } else if (time > old.windowStart()) {
                // 如果请求的时间戳大于现存的窗口的开始时间
                // 说明当前的窗口已经是陈旧的,也就是属于已经过去的一个统计时长之外的数据
                // 因此需要重置窗口的数据
                if (updateLock.tryLock()) {
                    try {
                        // 尝试获取update锁成功
                        // 调用resetWindowTo方法重置
                        // if (old is deprecated) then [LOCK] resetTo currentTime.
                        return resetWindowTo(old, time);
                    } finally {
                        updateLock.unlock();
                    }
                } else {
                    // 如果获取锁失败,说明已经有其他线程获取锁并进行更新
                    // 因此调用线程让步 并进入下一次自旋循环
                    Thread.yield();
                }

            } else if (time < old.windowStart()) {
                // 如果请求的时间比现存的还小,直接返回一个空的,说明这次请求的时间戳已经陈旧了
                // Cannot go through here.
                return new WindowWrap<T>(windowLengthInMs, time, newEmptyBucket());
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值