Sentinel是分布式系统的防御系统。以流量为切入点,通过动态设置的流量控制、服务熔断等手段达到 保护系统的目的,通过服务降级增强服务被拒后用户的体验。
工作原理
ProcessorSlotChain
Sentinel 的核心骨架,将不同的 Slot 按照顺序串在一起(责任链模式),从而将不同的功能(限流、降级、系统保护)组合在一起。slot chain 其实可以分为两部分:统计数据构建部分(statistic)和判断部分(rule checking)。核心结构
Sentinel 将 ProcessorSlot
作为 SPI 接口进行扩展,使得 Slot Chain 具备了扩展的能力。您可以自行加入自定义的 slot 并编排 slot 间的顺序,从而可以给 Sentinel 添加自定义的功能。
版本说明
https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E
在sentinel里面,所有的资源都对应一个资源名称(resourceName),每次资源都会创建一个Entry对象。每个Entry可以通过对主流框架的适配自动创建,也可以通过注解的方式或调用SphU API 显示创建。Entry创建的时候,同时也会创建一系列功能插槽(Slot chain),这些插槽有不同的职责,例如默认情况下会创建一下7个插槽:
-
NodeSelectorSlot 负责收集资源的路径,并将这些资源的调用路径,以树状结构储存起来,用于根据调用路径来限流降级;
-
ClusterBuilderSlot 用于存储资源的统计信息以及调用者信息,例如该资源的RT,QPS,thread count等,这些信息将用于多维度限流,降级的依据,对应簇点链路;
-
StatisticSlot 用于记录、统计不同维度的runtime指标监控信息;
-
FLowSlot 用于根据预设的限流规则以及前面slot 统计的状态,来进行流量控制,对应流控规则;
-
AuthoritySlot 根据配置的黑白名单和调用来源信息,来做黑白名单控制,对应授权规则;
-
DegradeSlot 通过统计信息以及预设的规则,来做熔断降级,对应熔断规则;
-
SystemSlot 通过系统的状态,例如load1等,来控制总的入口流量,对应系统规则;
重要的概念: -
slot chain:插槽
-
Node:根节点
-
Context:对资源操作时的上下文环境,每个资源操作(
针对Resource进行的entry/exit
)必须属于一个Context,如果程序中未指定Context,会创建name为"sentinel_default_context"的默认Context。一个Context生命周期内可能有多个资源操作,Context生命周期内的最后一个资源exit时会清理该Context,这也预示这真个Context生命周期的结束。 -
Entry:表示一次资源操作,内部会保存当前调用信息。在一个Context生命周期中多次资源操作,也就是对应多个Entry,这些Entry形成parent/child结构保存在Entry实例中
官方案例
改写官方案例代码
只有一个资源情况
多个资源的情况
Sentinel源码解析-Node之间的关系
- Node: 接口,sentinel里面的各种种类的统计节点
- StatisticNode: 统计节点,是Node的实现类,用于完成数据统计
- EntranceNode: DefaultNode的子类,入口节点,一个Context会有一个入口节点,用于统计当前Context的总体流量流量,统计维度为Context
- DefaultNode: 默认节点,用于统计一个Resource在当前Context中的流量数据,DefaultNode持有指定的Context和指定的Resource的统计数据,意味着DefaultNode是以Context和Resource为维度的统计节点
- ClusterNode:ClusterNode保存的是同一个Resource的相关统计信息,是以Resource为维度的,不区分Context,这和DefaultNode是有区别的
Node之间的关系
Node 接口定义了一个 Node 类所需要提供的各项指标数据统计的相关功能,为外部屏蔽滑动窗口的存在。提供记录请求被拒绝、请求被放行、请求处理异常、请求处理成功的方法,以及获取当前时间窗口统计的请求总数、平均耗时等方法。
源码入口分析
总结流程
利用aop进行
1.创建资源操作对象
2.从当前线程中获取context
3.对context进行判断,是否超过阙值(是否为NullContext,是的话不需要检测直接返回)
4.context是否为空,为空的话对context进行构建
5.创建调用链SlotChain(,类似于mvc中的Filter),进行限流检测
5.如果没被限流执行原方法
Sentinel源码解析-构建Context
SlotChain入口解析
slotChainBuilder.build();
主要作用:
创建defaultProcessorSlotChain
通过SPI读取com.alibaba.csp.sentinel.slotchain.ProcessorSlot 文件中的所有Slot
获取到的Slot转成AbstractLinkedProcessorSlot
//针对资源操作
chain.entry(context, resourceWrapper, null, count, prioritized, args);
根据ProcessorSlot文件中的顺序依次执行(节点触发顺序,下图)
NodeSelectorSlot
触发下一个节点
ClusterBuilderSlot
StatisticSlot
StatisticSlot是Sentinel 最为重要的类之一,用于根据规则判断结果相对应的统计操作。
entry方法 :依次之后后面的slot(核心的是FlowSlot流量控制,DegradeSlot熔断降级)。每个slot触发流控的话会抛异常(BlockException的子类)。若有BlockException抛出,则记录block数据;若无异常抛出则可以算通过(pass),记录pass数据。
exit方法:若无error(无论是业务异常还是流控异常),记录complete(success)以及RT,线程数-1。
记录数据的维度:线程数+1、记录当前DefaultNode数据、记录对应的originNode数据(若存在Origin)、累计IN统计数据(若流量类型为IN)。
fireEntry
FlowSlot
这个slot主要根据预设的资源的统计信息,按照固定的次序,依次生效。如果一个资源对应两条或多条流控规则,则会根据下次序依次检验,直到全部通过或有一个规则生效为止:
- 指定应用生效的规则,及针对调用方限流的;
- 调用方位other规则
- 调用方为default规则
核心方法
FlowRule(流控规则)继承自AbstractRule
AbstractRule的核心类型
private String resource; //资源名称
private String limitApp; //资源的来源
主要规则来源于dashboard
这里涉及到两个算法
- 令牌桶算法(信号量):令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。
- 漏斗算法(线程池):漏桶算法思路很简单,请求先进入到漏桶里,漏桶以固定的速度出水,也就是处理请求,当水加的过快,则会直接溢出,也就是拒绝请求,可以看出漏桶算法能强行限制数据的传输速率。
FlowSlot全部流控规则
检测并且应用流量规则
canPassCheck方法
passLocalCheck
针对不同的流控模式,利用对应的控制器来处理
FlowSlot校验大致规则
1.获取到指定资源的所有流控规则
2. 逐个应用流控规则flowRule
3.判断是集群还是单节点
4.根据请求选取节点
5.执行对应的flowrule 限流规则
6.下一条
熔断降级DegradeSlot
核心方法
真正判断是否需要开启熔断器是在exit方法中进行的,这个方法在业务方法执行后调用了,熔断器需要业务异常或业务的执行时间来判断是否开启熔断
CircuitBreaker熔断器
熔断策略