
从上述架构图中可以看出Sentinlel的核心就是一个处理链,一次请求过来会经过处理链上的多个slot处理,来进行熔断降级,流控等核心功能,对应每个slot的具体实现我们在后续会逐一进行讲解。
在上篇源码环境搭建的时候我们通过在方法上标注
@SentinelResouce注解来表示这个是sentinel的一个资源,然后就在sentinel- dashboard上面配置对应的流控规则来实现限流逻辑。注解的处理逻辑是在SentinelResourceAspect这个切面中进行处理

这里首先判断注解中有没有指定资源名,如果指定了资源名就用注解指定的,如果没有指定资源名,则通过解析方法,通过通过方法所在类+方法名+方法参数类名拼接出来一个资源名

这里会真正调用
Env的sph的entryWithType来执行真正处理逻辑。

这里我们发现:
sph的一个具体实现是CtSph- 在
Env的静态代码块中会调用InitExecutor#doInit方法

在
initExecutor#doinit方法中会去加载初始化组件,会通过spi加载对应的初始化组件,找到InitFunc的实现类,并排序进行初始化操作。

这里看好像是环境的初始化操作,初始化需要的对应组件,不是主线逻辑,我们在Env中已经知道
sph的具体实现是CtSph,我们继续追踪下CtSph#entryWithType方法。

- 这里把
name,entryType和ResourceType包装成一个ResourceWrapper- 继续调用
entryWithPriority方法

- 首先会给当前线程绑定一个context
- 查找对应的slotChain,也就是对应对这个资源的一个处理链
- 调用chain#entry方法对资源进行过处理链的操作

这里会调用
contextHolder#get方法,contextHolder是一个ThreadLocal,如果从ThreadLocal中没有获取到当前线程的context,则后续会调用InternalContextUtil#internalEnter方法初始化一个context放进来

这里我们看到
ContextUtil的静态代码块中会调用initDefaultContext方法来初始化默认的上下问,首先通过Constants.ROOT创建一个root节点,然将新创建的Node节点加入到root的字节点中,并存入contextNameNodeMap中

首先是这个Tree,这个Tree是由NodeSelectorSlot这个插槽来创建的,每创建一个树都有一个Root节点,这个Root节点就代表的是一个应用,一个应用只会创建一个Root节点。就比如说一个一个dubbo项目中会有provider和consumer,这一个consumer就是一个应用。

一个应用中可以定义很多资源可以是代码块、方法等等:

当属于同一个应用下的请求过来后,会首先判断是否有
Root,没有的话就会新建一个Root节点。
再往下就会出现EntranceNode、DefaultNode、CLusterNode三种node,那这三种节点又是什么关系呢?我们首先看一下这三个节点类的关系图:其中
StatsticNode是用作数据统计的,那根据继承关系其三个子类Node也是进行数据统计,那他们分别的作用又是什么呢?
在讲这三个Node前,大家要明白Sentinel的一个核心概念Context:
Context是对资源操作的上下文,每个资源操作必须属于一个Context。它会保存一次资源访问链路元数据和该资源所对应的实时信息,链路的各个节点都能通过获取链路绑定的context来获取一些信息进行相应的处理。如果代码中没有指定Context,则会创建一个name为sentinel_default_context的默认Context。一个Context生命周期中可以包含多个资源操作。Context生命周期中的最后一个资源在exit()时会清理该Conetxt,这也就意味着这个Context生命周期结束了。

Node:用于完成数据统计的接口
StatisticNode:统计节点,是Node接口的实现类,用于完成数据统计
EntranceNode:入口节点,一个Context会有一个入口节点,用于统计当前Context的总体流量数据
DefaultNode:默认节点,用于统计一个资源在当前Context中的流量数据
ClusterNode:集群节点,用于统计一个资源在所有Context中的总体流量数据

如果发现当前请求线程如果没有绑定
context,则给当前线程绑定一个名为sentinel_default_context的context

- 首先根据当前资源从缓存中获取处理链
- 没有获取到则调用
SlotChainProvider#newSlotChain构造处理链

- 这里首先通过
SPI方式创建builder,如果你没有指定则会创建一个DefaultSlotChainBuilder。

- 这里会创建一个
ProcessorSlotChain- 通过
SPI机制获取对应的处理链中的slot,这里会去sentinel-core/src/main/resources/META-INF/services找对应的Slot然后进行初始化- 把
slot添加到处理链中


这里会调用到处理链中的具体的
slot,每个slot的具体实现我们后续文章继续分析。
