sentinel源码分析-09流量整形控制器

sentinel 滑动时间窗口算法 sentinel 滑动时间窗口的算法 为什么要用滑动时间窗口算法? 原始的计数器算法 计数器算法的实现比较简单,在启动时候,设置一个初始的时间,然后设置一段时间interval作为滑动时间,如果请求方法时候进来的时间在这个区间内,并且没有超过控制值,就return true。 /** * 最简单的计数器限流算法 */ public class Counter { public long timeStamp = System.currentTimeMillis(); // 当前时间 public i 阅读详情

流量整形控制器

上面我们已经介绍了默认的快速失败流量整形控制器DefaultController,本节我们介绍其他几个控制器

RateLimiterController

匀速通过,漏斗算法

@Override
public boolean canPass(Node node, int acquireCount, boolean prioritized) {
    // Pass when acquire count is less or equal than 0.
    if (acquireCount <= 0) {//请求通过数为0,直接返回true
        return true;
    }
    // Reject when count is less or equal than 0.
    // Otherwise,the costTime will be max of long and waitTime will overflow in some cases.
    if (count <= 0) {//允许通过的大小小于0直接返回false
        return false;
    }

    long currentTime = TimeUtil.currentTimeMillis();
    // Calculate the interval between every two requests.
    //计算两个请求之间的间隔时间
    long costTime = Math.round(1.0 * (acquireCount) / count * 1000);

    // Expected pass time of this request.
    //此请求的预期通过时间
    long expectedTime = costTime + latestPassedTime.get();

    if (expectedTime <= currentTime) {//说明本应该发生的时间比这个当前时间小,那么说明可以通过
        // Contention may exist here, but it's okay.
        //这里可能存在竞争,但没关系
        latestPassedTime.set(currentTime);
        return true;
    } else {
        // Calculate the time to wait.
        //计算需要等待的时间
        long waitTime = costTime + latestPassedTime.get() - TimeUtil.currentTimeMillis();
        //如果需要等待的时间超过了最大等待时间则限流
        if (waitTime > maxQueueingTimeMs) {
            return false;
        } else {
            //本该执行的时间
            long oldTime = latestPassedTime.addAndGet(costTime);
            try {
                //等待的时间
                waitTime = oldTime - TimeUtil.currentTimeMillis();
                if (waitTime > maxQueueingTimeMs) {
                    latestPassedTime.addAndGet(-costTime);
                    return false;
                }
                // in race condition waitTime may <= 0
                if (waitTime > 0) {//线程阻塞等待
                    Thread.sleep(waitTime);
                }
                return true;
            } catch (InterruptedException e) {
            }
        }
    }
    return false;
}

这里首先计算两个请求之间的间隔时间costTime,通过costTime计算下次请求可以通过的时间expectedTime,如果expectedTime <= currentTime说明当前时间已经到达expectedTime ,则请求可以正常通过,否则说明当前时间请求需要等待,计算等待时间waitTime,如果waitTime比设置的最大等待时间大则直接不允许通过,如果没有达到最大排队时间则等待waitTime后通过。

WarmUpController

关注控制每秒传入请求的计数,类似于令牌桶算法

几个属性

protected double count;//可以通过的总数
private int coldFactor;//最小的冷加载因子
protected int warningToken = 0;//起始预热token数
private int maxToken;//最大token数
protected double slope;//斜率
//令牌桶
protected AtomicLong storedTokens = new AtomicLong(0);
//上一次填充时间
protected AtomicLong lastFilledTime = new AtomicLong(0);

构造函数

public WarmUpController(double count, int warmUpPeriodInSec, int coldFactor) {
    //count:预热流量控制阈值计数
    //warmUpPeriodInSec:预热时间默认10s
    //coldFactor:冷加热因子默认为3
    construct(count, warmUpPeriodInSec, coldFactor);
}


private void construct(double count, int warmUpPeriodInSec, int coldFactor) {

    if (coldFactor <= 1) {
        throw new IllegalArgumentException("Cold factor should be larger than 1");
    }

    this.count = count;

    this.coldFactor = coldFactor;
    // warningToken = 50;
    //起始预热token数量
    warningToken = (int)(warmUpPeriodInSec * count) / (coldFactor - 1);
    // maxToken = 100
    //最大的token数
    maxToken = warningToken + (int)(2 * warmUpPeriodInSec * count / (1.0 + coldFactor));

    //增长
    slope = (coldFactor - 1.0) / count / (maxToken - warningToken);//2/10/50=0.004

}

检查是否可以通过

@Override
public boolean canPass(Node node, int acquireCount, boolean prioritized) {
    long passQps = (long) node.passQps();
    //最后一个窗口的QPS
    long previousQps = (long) node.previousPassQps();
    syncToken(previousQps);

    // 开始计算它的斜率
    // 如果进入了警戒线,开始调整他的qps
    long restToken = storedTokens.get();
    if (restToken >= warningToken) {//QPS不是很高
        long aboveToken = restToken - warningToken;
        // 消耗的速度要比warning快,但是要比慢
        // current interval = restToken*slope+1/count
        //计算当前通过的最大QPS
        double warningQps = Math.nextUp(1.0 / (aboveToken * slope + 1.0 / count));
        if (passQps + acquireCount <= warningQps) {//没有达到最大QPS,则允许通过
            return true;
        }
    } else {
        //当前系统处理高QPS状态
        if (passQps + acquireCount <= count) {
            return true;
        }
    }

    return false;
}

填充令牌桶数量

protected void syncToken(long passQps) {
 //当前时间
 long currentTime = TimeUtil.currentTimeMillis();
 currentTime = currentTime - currentTime % 1000;
 //上次填入的时间
 long oldLastFillTime = lastFilledTime.get();
 if (currentTime <= oldLastFillTime) {//间隔时间太小,不能添加token
     return;
 }
 //原来的总token数
 long oldValue = storedTokens.get();
 //计算新的token数
 long newValue = coolDownTokens(currentTime, passQps);
 //修改总的token数
 if (storedTokens.compareAndSet(oldValue, newValue)) {
     //需要减去已经通过的QPS个数
     long currentValue = storedTokens.addAndGet(0 - passQps);
     if (currentValue < 0) {
         storedTokens.set(0L);
     }
     //设置上面装填token的时间
     lastFilledTime.set(currentTime);
 }

}

private long coolDownTokens(long currentTime, long passQps) {
    //原来的token数
    long oldValue = storedTokens.get();
    long newValue = oldValue;

    // 添加令牌的判断前提条件:
    // 当令牌的消耗程度远远低于警戒线的时候
    if (oldValue < warningToken) {//说明系统的QPS很高
        //新的token数
        newValue = (long)(oldValue + (currentTime - lastFilledTime.get()) * count / 1000);
    } else if (oldValue > warningToken) {
        if (passQps < (int)count / coldFactor) {//说明系统的QPS很低,正在预热
            newValue = (long)(oldValue + (currentTime - lastFilledTime.get()) * count / 1000);
        }
    }
    //新的token数不能超过最大token数
    return Math.min(newValue, maxToken);
}

这里我们假设count=10,warmUpPeriodInSec,coldFactor默认为3,可以计算出来warningToken=50而maxToken=100,首先计算一下距离上次放入token的时间,如果还没达到再次放入的时间则直接返回。获取剩余token的数量,如果比warningToken低,说明当前负载高则放入token,如果oldValue > warningToken说明系统负载低,正在预热,判断前一个时间窗通过的qps是否小于count / coldFactor,如果是则也放入令牌。计算warningQps这里我们假设aboveToken 为10,Math.nextUp(1.0 / (aboveToken * slope + 1.0 / count))约等于7.14,当passQps + acquireCount <= warningQps时已经通过QPS和本地通过数量小于越热值才能通过。

WarmUpRateLimiterController

还有一个流量整形控制器是WarmUpRateLimiterController,融合了WarmUpController和RateLimiterController

@Override
public boolean canPass(Node node, int acquireCount, boolean prioritized) {
    long previousQps = (long) node.previousPassQps();
    //更新令牌数量
    syncToken(previousQps);

    long currentTime = TimeUtil.currentTimeMillis();
    //令牌数量
    long restToken = storedTokens.get();
    long costTime = 0;
    long expectedTime = 0;
    //预热数量已经达到
    if (restToken >= warningToken) {
        //超过预热数量
        long aboveToken = restToken - warningToken;

        // current interval = restToken*slope+1/count
        //计算预热可以通过的qps
        double warmingQps = Math.nextUp(1.0 / (aboveToken * slope + 1.0 / count));
        //请求通过间隔时间
        costTime = Math.round(1.0 * (acquireCount) / warmingQps * 1000);
    } else {
        costTime = Math.round(1.0 * (acquireCount) / count * 1000);
    }
    //请求可以通过时间
    expectedTime = costTime + latestPassedTime.get();
    //时间已经到达,可以通过
    if (expectedTime <= currentTime) {
        latestPassedTime.set(currentTime);
        return true;
    } else {
        //需要等待一段时间通过
        long waitTime = costTime + latestPassedTime.get() - currentTime;
        if (waitTime > timeoutInMs) {
            return false;
        } else {
            long oldTime = latestPassedTime.addAndGet(costTime);
            try {
                waitTime = oldTime - TimeUtil.currentTimeMillis();
                if (waitTime > timeoutInMs) {
                    latestPassedTime.addAndGet(-costTime);
                    return false;
                }
                //等待
                if (waitTime > 0) {
                    Thread.sleep(waitTime);
                }
                return true;
            } catch (InterruptedException e) {
            }
        }
    }
    return false;
}
六、Alibaba sentinel之限流原理分析 1、找到该文件,打开 2、代码如下: 有一个TimeTicker线程在做统计,每1秒钟做一次。有N个RunTask线程在模拟请求,被访问的business code被资源key保护着,根据规则,每秒只允许20个请求通过。 package com.sentinel.sentinel.test; import com.alibaba.csp.sentinel.Entry; import com.alibaba.csp.sentinel.SphU; import com.alibaba.cs.. 阅读详情

相关推荐

避开这些坑,你的Python爬虫才能稳定爬取IEEE Xplore(含反爬策略与MongoDB存储实战)

本文详细介绍了如何构建稳定的Python爬虫系统以爬取IEEE Xplore学术论文,包括反爬策略、MongoDB存储优化和断点续传机制。通过动态等待时间算法、请求头指纹管理和会话保持策略,有效应对IEEE的反爬机制。同时,优化MongoDB数据结构和索引,提升存储效率。最后,强调法律合规与伦理考量,确保爬虫合法合规运行。

weixin_29031057的博客 1095

限流降级神器-哨兵(sentinel)原理分析

Sentinel是阿里中间件团队开源的,面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。 大家可能会问:Sentinel 和之前常用的熔断降级库Netflix Hystrix有什么异同呢?Sentinel官网有一个对比的文章,这里摘抄一个总结的表格,具体的对比可以点此链接查看。 对比内容 Sentinel Hystrix 隔离策略 信号量隔离 线程池隔离/信号量隔离 熔断降...

weixin_42073629的博客 6263

VBA中如何使用Edge内核Browser?

在微软宣布停止对IE的支持后,许多使用VBA中Web Browser的用户遇到了困境,因为Web Browser使用的IE内核。然而微软并没有给出支持Edge的新版Web Browser,网上许多第三方的库也不够完善。经过调研,libEdge可以较好的和VBA集成,实现在Excel中打开Browser,甚至能够通过执行js代码,获取web页面的信息。项目需要WebView2Loader.dll和LibEdge.dll两个库,区分x86和x64版本。

金木AI 2396

Sentinel 实战:如何实施流量整形与限流策略?

Sentinel 如何实施流量整形与限流策略!

zgz15515397650的博客 783

PLCopen运动控制避坑指南:单轴功能块常见报错排查(基于SM3_Basic函数库)

本文深入解析PLCopen运动控制中单轴功能块的常见报错问题,基于SM3_Basic函数库提供实用排查指南。从功能块逻辑错误与硬件报错的甄别技巧到高频报错场景的解决方案,帮助工程师快速定位并解决运动控制系统中的稳定性问题,提升工业自动化设备的运行效率。

weixin_33686714的博客 314

IEPE传感器4mA恒流源接口电路

另外传感器的偏置电压大概在10V多点,一般接个电容把直流分量去掉。这里我们要把恒流源的电流设置在4毫安左右,R1取33Ω差不多正好。经过CR的隔直流电路后的波形是这样的。

老白的博客 6107

Sentinel学习笔记(1)-- 流量统计代码解析

  代码解析博客地址:https://www.jianshu.com/p/7936d7a57924 结论图: 总结:slot Chain 是整体的一个骨架结构,之间的传导数据是entry.所有slot Chain 获取的基本数据都在Entry中。Entry 代表着一个信号,代表一个请求的到来,若果没有报任何错误,就按照正常的时间框算法进行统计。 可以看出Entry在统计这个数据中扮...

dainandainan1的博客 1352

【微服务】Spring Aop原理深入解析

spring原理深度解析

congge 1万+

14. Sentinel滑动时间窗口算法源码解析

上节课我们分析了Sentinel的滑动时间窗口算法原理,那么这节课我们来研究一下源码中的具体实现 1. Sentinel中使用滑动时间窗的流程图 从图中可以看出Sentinel在各种地方都使用了时间窗提供的数据。 也是依赖Sentinel的StatisticSlot提供数据由时间窗记录下来。 2. 源码入口分析 首先看StatisticSlot.entry方法中node.addPassRequest(count)方法,这里我之前就提到过用到了滑动窗口算法,那我们来具体分析 // Stat..

1264

VTK 显示大量点云数据及交互(点云拾取、着色、测量等)功能

VTK (Visualization Toolkit) 是一个强大的开源可视化库,非常适合处理点云数据。下面将介绍如何使用 VTK 显示大量点云数据,并实现点云拾取、着色、测量等功能。

深之JohnChen的专栏 1992

slew dreate,slew threshold与transition计算

​只看rise情况下,from pin取slew threshold10%-90%的区间,slew derate为1,计算得到transition为1.002e-10,to pin的slew threshold 为30%-70%,slew derate 0.5,从波形列表上取相近的值3.75e-10和8.75e-10,计算得到transition为(8.75e-10-3.75e-10)/0.5=1e-9,考虑精度和取值区间问题,基本符合工具计算的值,如下:​。如下示例,在.lib库中有定义以下内容。

m0_61544122的博客 791

吃透阿里P8资深架构师写的Sentinel 源码解析 看完绝对涨技术!

提示:关注+转发本文+私信我“资料”,可获取更多电子书、技术教程、视频、大厂面试题等学习资料。 本文介绍阿里开源的 Sentinel 源码,GitHub: alibaba/Sentinel,基于当前(2019-12)最新的 release 版本 1.7.0。 简介 Sentinel 的定位是流量控制、熔断降级,你应该把它理解为一个第三方 Jar 包。 这个 Jar 包会进行流量统计,执行流量控制规则。而统计数据的展示和规则的设置在 sentinel- dashboard 项目中,这是一个...

sunjian286的专栏 1334

Sentinel限流、整形、熔断降级介绍

文章目录名词解释集群模式规则种类功能介绍流量控制熔断降级系统保护访问控制热点规则网关流控集群流控名词介绍独立模式嵌入模式动态规则架构API模式DataSource模式**DataSource 扩展常见的实现方式有:**Sentinel 目前支持以下数据源扩展:gateway 动态路由配置参考文档 名词解释 集群模式 集群流控中共有两种身份: Token Client:集群流控客户端,用于向所属 Token Server 通信请求 token。集群限流服务端会返回给客户端结果,决定是否限流。 Token S

kylin 1278

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

【微服务】Sentinel 适配网关进行流量控制

外部请求进入 API Gateway 时会经过 Sentinel 实现的 filter,其中会依次进行路由/API 分组匹配、请求属性解析和参数组装。Sentinel 会根据配置的网关流控规则来解析请求属性,并依照参数索引顺序组装参数数组,最终传入SphU.entry(res, args)中。Sentinel API Gateway Adapter Common 模块向 Slot Chain 中添加了一个GatewayFlowSlot,专门用来做网关规则的检查。......

qq_57756904的博客 3288

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

spring cloud alibaba 学习(二十)Sentinel 预热限流

目录前言一、pandas是什么? 前言 一、pandas是什么? Warm Up 调用了WarmUpController#canPass(...) 这边主要使用的是令牌桶算法 //构建函数 private void construct(double count, int warmUpPeriodInSec, int coldFactor) { //冷因子不能小于1,默认为3 if (coldFactor <= 1) { th..

码易的博客 1214

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

WarmUpController原理

Sentinel 中冷启动过滤器WarmUpController原理

weixin_43063328的博客 585

Sentinel : 服务容错(降级熔断、流量整形)

Sentinel 是 Spring Cloud Alibaba 的一款服务容错组件,我们也经常把它叫做“防流量哨兵”。它是阿里巴巴双十一大促核心场景的保护神,内置了丰富的服务容错应用场景。它以流量作为切入点,通过各种内外防控手段达到维持服务稳定性的目的。。

li12412414的博客 634

我理解的Sentinel:时间窗统计

1 时间窗口基础 参数: intervalLength: 区间长度,即统计的时间长度,决定了计算数据时统计的窗口个数 windowLength:时间窗宽度 count:时间窗内统计量 startTime: 每个时间窗的起始时间 如下图所示,每个时间点都会归属于一个时间窗口,即会将时间轴按照时间窗宽度windowLength进行划分。每个时间窗都有一个起始时间startTime。 获取某个时间的统计量 获取当前时间currTime 根据currTime - (已用时间窗).startTime <

xiaojkql的博客 2037

【spring系列】Alibaba Sentinel(4)滑动窗口源码

之前简单的使用了下sentinel,通过sentinel实现了简单的流控降级的示例,sentinel真正的奥妙缺在这个滑动窗口,通过滑动窗口来记录每个时间段是否可以通过限制。

叁滴水 的博客 2021

请求令牌 接口_Sentinel接口限流三板斧

目录前言背景限流的算法Sentinel 限流设计梳理Sentinel 实战前言哨兵(Sentinel)是指站岗、放哨、巡逻、稽查的士兵,并根据作战策略实施作战计划。背景《稳定性之接口监控》一文中提及到针对接口监控制定了监控报警阀值触发机制。`单位时间内报警次数达到阀值后触发报警,本身报警触发机制的实现其实与监控限流大同小异。所以在监控报警触发的机制设计参考了监控限流的实现方案。限流的实...

weixin_33785971的博客 750

Sentinel使用教程

sentinel spring cloud alibaba

tttalk的博客 7816

Sentinel 体系结构:什么是服务容错(降级熔断、流量整形)?

今天我们来这篇文章来讲一下大型微服务系统中高可用性的重要一环:服务容错。通过这篇文章的内容,你可以了解什么是降级熔断和流量整形,以及它们和服务高可用之间的联系。最后再从架构层面去了解 Sentinel 服务容错的工作流程。说到高可用,你也许会不由自主地想到“集群化”。没错,通过搭建服务集群来避免单点故障确实是高可用性保障的常规操作。但是,仅仅搭建集群就能高枕无忧了吗?当面对真正的高可用杀手“服务雪崩”时,即便是集群也会显得脆弱无力。那么服务雪崩在微服务系统中能引起多大的故障呢?在正文开始前,我们先来了解一下

zgz15515397650的博客 319

sentinel之三种熔断降级情况的验证

熔断降级是指当资源处于不稳定的情况下,在接下来的时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出DegradeException)。 通常用三种方式来衡量资源是否处于稳定的状态: 平均响应时间 (DEGRADE_GRADE_RT):当资源的平均响应时间超过阈值(DegradeRule 中的 count,以 ms 为单位)之后,资源进入准降级状态。接下来如果持续进入 5 个请求,它们的 R...

Ramboll的博客 8479

Sentinel使用令牌桶实现预热【原理源码】

前言Sentinel的QPS流控效果有快速失败、预热模式、排队等待、预热+排队等待模式,本文主要分析预热模式中是如何使用令牌桶算法限流的。一、流控效果源码结构在FlowRule更新缓...

gaoliang1719的专栏 1875

Sentinel基本使用--基于QPS流量控制(二), 采用Warm Up预热/冷启动方式控制突增流量

一, Warm Up Sentinel的Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。warm up冷启动主要用于启动需要额...

xiongxianze的博客 5634
上一篇: sentinel源码分析-08流量数据统计
下一篇: elasticsearch源码分析-01服务启动
胖柯G
博客等级 码龄10年 453粉丝 57原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值