Sentinel
-
Sentinel是一个轻量级的流控架构,主要以流量为切入点,从流量控制,熔断,系统负载保护等多个维度来帮助用户保护服务的稳定性。
-
与Hystrixx相比,Sentinel设计更简单,使用更方便灵活,能动态的修改限制规则
-
Sentinel的设计中资源定义和 规则配置,还有流控算法三者是分开的,我们可以通过Sentinel api先定义好资源埋点,然后需要的时候我们在实时的增加上流控规则。这种方式极大的增加了Sentinel的灵活性。
-
官网定义:
- Sentinel带来的性能损耗:在单机25W QPS 的时候才会有显著影响5%~10%,单机QPS不大可以忽略不计
-
Sentinel 提供两种埋点方式:
- try-catch方式 (通过SphU.entry)通过这种方式做资源定义的时候,如果触发限流或者熔断,会抛异常BlockException
- if-else 方式(通过SphUO.entry),当方法返回false的时候就是异常处理的时机
Sentinel 工作流程
- Sentinel所有资源都对应资源名称 resourceName,资源创建方式有
- 自动适配,比如定义的接口都会自动适配生成对应的资源
- 通过SphU api手动创建
- 通过@SentinelResource注解手动创建
- 每创建一个资源都会创建一个Entry,同时也会跟随着创建一系列的功能插槽Slot,这些插槽默认创建7 个,每一个插槽职责不同,Sentinel通过这些插槽功能完成各种维度数据统计,以及限流,熔断操作。
Sentinel Node之间的关系
- Sentinel 每对应一个资源都创建默认7个Slot,利用Slot的功能完成数据统计,限流实现
- Sentinel数据统计过程中会根据资源的各个维度进行统计,并且存储在不同类型的Node中,其中每个Node存储的数据维度不同,有如下几种Node节点了类型

- Node:Node节点根接口类,定义了Node节点应该具有的功能点
- StatisticNode: 统计节点,用来完成数据统计
- EntranceNode:入口节点,入口流量的容积,他说每一个Context的入口节点,用来统计当前Context的总体流量数据
- DefultNode:默认节点,用于在Resource + Context维度来统计数据
- ClusterNode :用于在Resource维度的同价数据,不区分Context

- 如上图中
- 每个Context对应一个EntranceNode,例如默认的每一个接口都有一个流量统计EntranceNode
- 对应每一个source对应一个DefaultNode,例如在每个请求过程中,我们可以定义多个@SentinelResource注解的方式增加资源,例如有多个方法需要流控,并且他会在同一个接口触发,那就会导致一个Context中可能存在多个resource,因此会有多个DefaultNode
- 在DefaultNode2中他可能是自定一的一个限流方法,他可能被接口A调用,也可能被接口B调用,那么流量信息久会分布在ContextA与ContextB中,因此对resource2的总资源统计久由ClusterNode2 完成,因此维度是Context + resource
Sentinel 加载入口
- 因为Sentinel资源生成方式有三种,上面也介绍了,分别是Sphu.entry手动调用API,@SentinelResource 注解,系统自动生成调用链路生成
- 其中第一点是不用分析的,他直接调用Sentinel的API来完成
- 下面先说一下自动化生产的情况
自动生成连路资源方式 SentinelWebAutoConfiguration
- 引入依赖spring-cloud-starter-alibaba-sentinel中,依托SpringBoot的自动装配原理,会先去加载META-INFO/services 下的配置文件,其中spring.factories中配置了部分需要加载的类的全限定名。其中和自动连路生产相关的类是SentinelWebAutoConfiguration
- 在SentinelWebAutoConfiguration类定义中,他实现了WebMvcConfigurer,我们可以通过WebMvcConfigurer 来实现自定义拦截器
- 我们通过实现自己的addInterceptors方法来对接口的PathPatterns 进行拦截,默认情况设置的是/**,也就是对所有接口进行拦截,并且生成资源

注解SentinelResource方式
- 同样在spring-cloud-stater-alibaba-sentinel中依赖自动装配机制,在META-INFO/service路径下加载spring.factories,本次关键类是SentinelAutoConfiguration
- 在SentinelAutoConfiguration中定义了一个sentinelResourceAspect方法,这个方法通过spring AOP的方式定了切点为 SentinelResource的注解,以及一个Around的增强逻辑,通过AOP的环绕通知来进行增强
- 在增强方法中他同样也是通过SphU.entry来创建context,统计数据,并做流控等检查
entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());
- 在entry的最终实现中,首先会获取一个Context,Context是每一个请求必备的一个对象,因为每个请求都会占用一个线程,并且绑定一个Context
- 如果没有在线程中获取到,那么会生成一个默认的 sentinel_default_context,并放入当前线程中
- 接着会执行lookProcessChain,这个方法是整个架构和核心方法,会在方法中构建一个处理链,这个处理链是一个单向链表结构,类似于Filter的链,
ProcessorSlot
- 接着来看下如何生成这个处理链的。
- 在lookProcessChain方法中,通过SlotChainBuilder 以及ProcessorSlot 类,分别通过SPI技术加载META-INFO/services中的接口全限定配置文件,然后由ServiceLoader实现类的加载。
- 在ProcessorSlot中久定义来我们需要加载默认7个slot,并且有默认的顺序
com.alibaba.csp.sentinel.slots.nodeselector.NodeSelectorSlot
com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot
com.alibaba.csp.sentinel.slots.logger.LogSlot
com.alibaba.csp.sentinel.slots.statistic.StatisticSlot
com.alibaba.csp.sentinel.slots.block.authority.AuthoritySlot
com.alibaba.csp.sentinel.slots.system.SystemSlot
com.alibaba.csp.sentinel.slots.block.flow.FlowSlot
com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot
-
在加载完7个默认Slot后,返回的是AbstractLinkedProcessorSlot>他事所有slot的抽象父类,他借鉴了链表的设计,每个对象中定义了一个next指针。最终形成了一个链表结构,如官网中图片

-
构建这个链表同时用了责任链模式,在这默认的7个Slot中,每一个的功能点都不同,并且都比较复杂,比如:数据统计,限流,降级,热点参数,系统降级等,如果都写在同一个类中,那么必然造成维护困难,而且耦合严重,
-
在OOP思想中,让每个类职责明确,因此通过责任链模式让每一个功能解偶并且用一个单向链表的数据结构将他们串联起来。
每个slot功能
- 如管网中描述,在每个Slot功能如下:
- NodeSelectSlot:负责收集资源的路径,就是我们在SentinelWebAutoConfiguration中通过拦截器得到的资源数据,将数据收集并且形成一个树状结构,在控制台中生成的那个树状结构数据就是通过这个节点生成的
- ClusterBuilderSlot:用于存储资源的统计信息,以及调用者信息,例如资源的RT,QPS,这个数据存储点就是ClusterNode节点
- LogSlot :记录日志
- StatisticSlot: 用于记录,统计不同维度的runtime指标监控,比如异常,超时类似这种
- AuthoritySlot: 这个根据配置的黑白名单和调用信息,做了一个权限控制
- SystemSlot :系统级别的流控,用来控制总流量的,在控制台可以设置规则
- FlowSlot: 最核心的限流,通过预设的流控规则,以及前面各种Slot中的统计数据进行流控,滑动窗口算法的核心实现
- DegradeSlot:熔断降级控制Slot,也是更具配置的熔断规则 ,并且依据StatisticSlot中统计的信息来最熔断降级。
