阿里大佬带你解密Sentinel
Posted Java-桃子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了阿里大佬带你解密Sentinel相关的知识,希望对你有一定的参考价值。
1、Sentinel 概念
1.1、代码结构
1.2、核心概念
Resource
资源是 Sentinel
对所保护的内容的抽象,任何想保护的代码
、函数
等都可以通过 SphU.entry 接口将其定义为一个资源,SphU.entry
接口的第一个参数描述了该资源的名称
Node
Node是sentinel中用来存储统计数据的内存结构,以树形结构和hash存储:
一个resource
按照不同入口设置不同统计结点,存储context
级别的统计信息;一个resource
下设置统一的cluster node
,存储resource粒度的统计信息;每个cluster node
根据来源下挂不同origin node
,存储各个来源的统计信息。
配置中不同限流模式其实最终对应的就是选择不同的node进行计算:
- 直接模式: 选择cluster node
- 关联模式: 选择关联resource的cluster node
- 应用涞源: 选择origin node
- 链路模式: 选择default node
Node 类型:
- StatisticNode:最为基础的统计节点,是后续三种节点的父类,包含秒级和分钟级两个滑动窗口结构。
- DefaultNode:链路节点,用于统计调用链路上某个资源的数据,维持树状结构。
- ClusterNode:簇点,用于统计每个资源全局的数据(不区分调用链路),以及存放该资源的按来源区分的调用数据
- EntranceNode:入口节点,特殊的链路节点,对应某个 Context 入口的所有调用数据。
Context
Context
是对资源操作时的上下文环境, 同一个线程中通过thread local
进行传里, context
中维护了currentEntry
, 同一个线程中可以多次entry/exit
, 所以entry
同样维护了一个树状结构:
Entry
调用点,这里面保存着和某一特定资源的某一次调用相关的信息,比如这次调用的起始执行时间,结束时间,是否抛出异常,调用链路中的父子关系,该调用点对应资源的处理链(ProcessorSlotChain
),还保存了该调用点所对应的资源统计节点
Slot
slot
是规则处理器,通过责任链模式进行串联处理。
1.3、核心类图
sentinel主要通过Node实现结点维护统计信息、通过LeapArray实现滑动窗口算法。
2、Sentinel 流程
2.1、规则配置
应用通过订阅监听模式实现各种监听器,监听然后对应不同配置的进行更新,图中列出了几个主要监听器,如: 规则配置、基本配置、集群配置等。
2.2、规则验证
应用调用entry入口即启动了规则验证流程,主要步骤为获取context, 构建并执行slot chain,如果违反规则纪录失败计数,清理contxt;反之,则纪录成功计数,返回验证成功。
3、Sentinel 核心
3.1、限流算法
我们所熟知的限流算法包括: 1. 计数器 2. 固定窗口 3. 滑动窗口 4.漏桶 5.令牌桶等。
- 1、
计数器
,维护一个计数器,访问进入计数器+1,如果超过阙值则拒绝、访问结束计数器-1。 - 2、
固定窗口
,给定一个时间窗口,维护一个计数器、如果窗口内访问次数大于阙值则拒绝。 - 3、
滑动窗口
,固定窗口有临界问题,所以提出滑动窗口思想,将一个大的时间窗口切分成更细粒度的子窗口,每个子窗口单独统计,每过一个子窗口的时间,就向右滑动一个子窗口。 - 4、
漏桶
,滑动窗口不能解决平滑度问题,为了解决平滑度问题,提出漏桶算法进行流速控制。 - 5、
令牌桶
: 跟漏桶算法相反,以很定的速度产生令牌,桶满则丢弃,请求访问时从桶里后去令牌,如果能够获取,则通过否则拒绝。
Sentinel
中主要使用了计数器
、滑动窗口
、漏桶
等限流思想
。比如对于线程数的流控
,就是直接使用计数器
进行限制,对于QPS的限制则
使用了滑动窗口
的思想,滑动窗口
也是Sentinel
的主要流控实现方式。
3.2、滑动窗口
Sentinel
支持秒级的窗口,默认窗口大小1秒
,假设分为5个子窗口
,则每个子窗口的大小为200ms
, 如上图,每个格子有个索引timeId
, 那窗口是如何进行滑动呢?算法的关键实现就是在前面类图提到过的currentWindow()
方法:
- 1、根据当前时间戳计算timeId
- 2、根据timdId获取当前子窗口
- 3、如果子窗口不存在,则创建子窗口
- 4、如果子窗口已经存在,则根据当前时间计算开始开始时间,对比子窗口的开始时间,如果开始时间一致,则说明此子窗口即当前窗口,如果大于子窗口时间,则需要滑动
- 5、滑动其实就是resetWidow, 包括reset windowStartTime, window中的统计信息等,如上图所示
3.3、优先级
优先级的目的是为了区分正常流量
和其他低优先级流量
,比如压测流量
。对于正常流量
,如果超过阙值
,不想直接拒绝,尝试借用将来窗口的指标,如果借用成功,则请求通过,如果借用失败,则拒绝。当时间窗口
真正走到将来的时间点时,需要将借用窗口的计数器
恢复设置。
那如何当前请求是否可以借用呢?如下图,主要维护一个借用时间阙值,计算一秒窗口内的总数有没有超过QPS,如果没有超过看借用时间是否超过借用阙值:
3.4、热点参数
一般资源的定义需要可枚举的,不能爆炸式的,假如对每个userId进行限流,这样会导致sentinel的存储空间爆炸式增长,最后导致OOM. 对于这种细粒度的参数限流,sentinel提供了热点参数方案。
如图:
热点参数就是在正常统计信息而外增加了参数统计,一样支持线程数和QPS两种限流方式,对于线程数,每个参数索引维护了一个LRU cache; 对于QPS,每个参数索引、每个子窗口、每个统计纬度维护了一个LRU cache, cache中维护了各种计数。通过LRU cache可以避免内存爆炸, 达到热点参数限流的目的。
以上是关于阿里大佬带你解密Sentinel的主要内容,如果未能解决你的问题,请参考以下文章
重磅来袭!不愧是阿里内部Spring Cloud Alibaba 电子版教程,阿里大佬带你打怪升级阿里P8
五分钟带你玩转spring cloud alibaba越玩越溜!实战Spring Cloud Alibaba Sentinel
五分钟带你玩转spring cloud alibaba越玩越溜!实战Spring Cloud Alibaba Sentinel