令牌桶、漏斗、冷启动限流在sentinel的应用

摘要:
从流限制的角度来看,Sentinel的流限制有两个控制维度,一个是qp,另一个是并发。canPassCheck){thrownewFlowException;}}//canPassCheck-˃passLocalCheckprivatestaticbooleanpassLocalCheck{returnrule.getRater().canPass;}目前,canPass验证具有以下实现类:这些实现类使用以下流限制算法:DefaultController:Token Bucket RateLimit Controller:Funnel WarmUpController:Cold Start Token Bucket WarmUpRateLimit Controller:Cold Start Funnel Sentinel统计信息,如qp、pass、block和其他信息在滑动时间窗口中维护,例如当时间戳是910时,统计信息将被更新到对应于800-1000的时间窗口。当时间戳为1001时,第一个时间窗口将被重用,因为只有五个时间窗口。此窗口的统计信息将在使用前初始化。

令牌桶、漏斗、冷启动限流在sentinel的应用第1张

 分布式系统为了保证系统稳定性,在服务治理的限流中会根据不同场景进行限流操作,常见的限流算法有:

  • 令牌桶:可容忍一定突发流量的速率的限流,令牌桶算法的原理是系统以恒定的速率产生令牌,然后把令牌放到令牌桶中,令牌桶有一个容量,当令牌桶满了的时候,再向其中放令牌,那么多余的令牌会被丢弃;当想要处理一个请求的时候,需要从令牌桶中取出一个令牌,如果此时令牌桶中没有令牌,那么则拒绝该请求。

  • 漏斗:固定速率限流,可以启动整流作用。

在分析sentinel限流之前,我们先看下sentinel是什么,官网说明如下:

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来帮助您保障微服务的稳定性。

从限流角度来看,sentinel的限流有2种控制维度,一个是qps,一个是并发数。

qps这个很好理解,也就是每秒处理请求量,当超过设定阈值时,会进行流控,策略有如下几种:拒绝、排队(一定时长)等。

并发数这个就是当前线程运行数,类似于hystrix,只不过sentinel是进行线程个数统计判断是否达到线程设定值,而hystrix是根据不同线程池来做的。

sentinel中处理流程是一个责任链,不同功能的逻辑抽象成不同的ProcessorSlot组合在一起,比如有限流的FlowSlot、打日志的LogSot、数据统计的StatisticSlot。下面重点看限流的com.alibaba.csp.sentinel.slots.block.flow.FlowSlot

public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count,
                  boolean prioritized, Object... args) throws Throwable {
    // 是否触发限流检查
    checkFlow(resourceWrapper, context, node, count, prioritized);
    // 继续往下一个节点走
    fireEntry(context, resourceWrapper, node, count, prioritized, args);
}

public void checkFlow(Function<String, Collection<FlowRule>> ruleProvider, ResourceWrapper resource,
                      Context context, DefaultNode node, int count, boolean prioritized) throws BlockException {
    Collection<FlowRule> rules = ruleProvider.apply(resource.getName());
    for (FlowRule rule : rules) { // 多个限流规则检查
        if (!canPassCheck(rule, context, node, count, prioritized)) {
            throw new FlowException(rule.getLimitApp(), rule);
        }
    }
}
// canPassCheck -> passLocalCheck
private static boolean passLocalCheck(FlowRule rule, Context context, DefaultNode node, int acquireCount,
                                      boolean prioritized) {
    return rule.getRater().canPass(selectedNode, acquireCount, prioritized);
}

canPass校验目前有以下几种实现类:

令牌桶、漏斗、冷启动限流在sentinel的应用第2张

这几个实现类分别使用了如下几种限流算法:

  • DefaultController:令牌桶

  • RateLimiterController:漏斗

  • WarmUpController:冷启动的令牌桶

  • WarmUpRateLimiterController:冷启动的漏斗

sentinel中统计信息,比如qps、pass、block等信息都是在滑动时间窗口中维护的,比如时间戳是910时,统计信息会往对应800-1000的时间窗口更新,当时间戳是1001时,由于时间窗口只有5个(每个200ms),因此会复用第一个时间窗口,在使用前会先进行初始化该窗口统计值。

令牌桶、漏斗、冷启动限流在sentinel的应用第3张

对于默认的流控实现 DefaultController,其是根据时间窗口的统计值是否达到了限流值来决定是否限流的,这也是把它归为令牌桶算法的原因。漏斗算法实现RateLimiterController,会记录上一次正常通过的时间戳信息(latestPassedTime),当判断是否限流时,会根据当前时间-latestPassedTime是否大于间隔值,大于的话表示可以正常通过,小于的话表示刚刚已经有流程正常通过,此次需要排队等待,等待时间为期望时间戳-当前时间戳,并发场景下,多个线程可能都会走到等待这里,因此需要(cas操作)判断当前需等待时间是否大于某个值,大于的话直接进行限流,不再排队等待。

冷启动限流算法,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。

sentinel中通常冷启动的过程系统允许通过的 QPS 曲线如下图所示:

令牌桶、漏斗、冷启动限流在sentinel的应用第4张

冷启动的两种模式,令牌桶和漏斗大同小异,只不过在流量较大时,冷启动过程 令牌桶走势类似于阶梯向上直到设定的限流值,漏洞走势类似于几个斜线向上之道设定的限流值。

关于sentinel更多的知识可参考官方文档:https://sentinelguard.io/zh-cn/docs/introduction.html

 推荐阅读 

免责声明:文章转载自《令牌桶、漏斗、冷启动限流在sentinel的应用》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇通用异常处理框架(转载)elastalert 配置post告警方式(备忘)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

iOS 启动时间优化

在 WWDC 2016 上首次提到了关于 App 应用启动速度优化的话题:Session 406 Optimizing App Startup Time。 一、冷启动与热启动 热启动是,APP会恢复之前的状态继续运行,这种就是热启动,我们平时所说的APP在后台的存活时间,其实就是APP能执行热启动的最大时间间隔。而冷启动则是APP从被加载到内存到运行的状态...

WPF 同一窗口内的多线程 UI(VisualTarget)

WPF 的 UI 逻辑只在同一个线程中,这是学习 WPF 开发中大家几乎都会学习到的经验。如果希望做不同线程的 UI,大家也会想到使用另一个窗口来实现,让每个窗口拥有自己的 UI 线程。然而,就不能让同一个窗口内部使用多个 UI 线程吗? 答案其实是——可以的!使用 VisualTarget 即可。 阅读本文将收获一份对 VisualTarget 的解读以...

堆栈信息分析

一、堆栈信息解读 2013-01-13 11:02:31 Full thread dump Java HotSpot(TM) Client VM (23.1-b03 mixed mode, sharing): "[ThreadPool Manager] - Idle Thread" daemon prio=6 tid=0x069a3400 nid=0x84...

【学习底层原理系列】Java底层-synchronized锁-2偏向锁篇

上一篇通过构建金字塔结构,来从不同的角度,由浅入深的对synchronized关键字做了介绍, 快速跳转:https://www.cnblogs.com/xyang/p/11631866.html 本文将从底层实现的各个“组件”着手,详细拆解其工作原理。 本文会分为以下2节内容:   第一节:介绍MarkWord和LockRecord两种数据结构,该知识点...

关于设置微信分享标题,图标

公众号端: 1.你得有一个公众号(订阅号、服务号) 2.当前网站域名加进公众号的js安全域名中(这一步必须,注意域名格式,已经将文件放入指定位置,域名一般会绑定一个路径到哪个文件夹,所以得将文件放入对的位置,否则不能添加) 3.当前网站服务器的ip加进公众号的ip白名单中(这一步必须,在公众号当中添加,否则在获取access_token的时候会获取不到,这...

编写多线程代码时,启动线程后等待线程结束方法

在编写多线程代码时,如果主线程结束,那么子线程也会随之结束,如何等待线程结束再往下执行。   等待线程执行完成代码。   线程代码:   package demo; import java.util.concurrent.CountDownLatch; public class NodeSqlThread1 implements Runnable{    ...