Sentinel源码解析-请求入口
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
文章目录
一、Sentinel架构
从上述架构图中可以看出Sentinlel
的核心就是一个处理链一次请求过来会经过处理链上的多个slot
处理来进行熔断降级流控等核心功能对应每个slot
的具体实现我们在后续会逐一进行讲解。
二、@SentinelResouce处理流程
1. SentinelResourceAspect-入口
在上篇源码环境搭建的时候我们通过在方法上标注
@SentinelResouce
注解来表示这个是sentinel
的一个资源然后就在sentinel- dashboard
上面配置对应的流控规则来实现限流逻辑。注解的处理逻辑是在SentinelResourceAspect
这个切面中进行处理
1.1 getResourceName(获取资源名)
这里首先判断注解中有没有指定资源名如果指定了资源名就用注解指定的如果没有指定资源名则通过解析方法通过通过方法所在类+方法名+方法参数类名拼接出来一个资源名
1.2 SphU#entry(核心增强逻辑)
这里会真正调用
Env
的sph
的entryWithType
来执行真正处理逻辑。
1.2.1. Env
这里我们发现
sph
的一个具体实现是CtSph
- 在
Env
的静态代码块中会调用InitExecutor#doInit
方法
1.2.2. InitExecutor#doInit
在
initExecutor#doinit
方法中会去加载初始化组件会通过spi
加载对应的初始化组件找到InitFunc
的实现类并排序进行初始化操作。
1.2.3.InitFunc实现类
这里看好像是环境的初始化操作初始化需要的对应组件不是主线逻辑我们在Env中已经知道
sph
的具体实现是CtSph
我们继续追踪下CtSph#entryWithType
方法。
1.2.4. entryWithType
- 这里把
nameentryType和ResourceType
包装成一个ResourceWrapper
- 继续调用
entryWithPriority
方法
1.2.5 entryWithPriority
- 首先会给当前线程绑定一个context
- 查找对应的slotChain也就是对应对这个资源的一个处理链
- 调用chain#entry方法对资源进行过处理链的操作
1.2.5.1 ContextUtil#getContext
这里会调用
contextHolder#get
方法contextHolder
是一个ThreadLocal
如果从ThreadLocal
中没有获取到当前线程的context
,则后续会调用InternalContextUtil#internalEnter方
法初始化一个context
放进来
1.2.5.2 ContextUtil#initDefaultContext
这里我们看到
ContextUtil
的静态代码块中会调用initDefaultContext
方法来初始化默认的上下问首先通过Constants.ROOT
创建一个root
节点然将新创建的Node
节点加入到root
的字节点中并存入contextNameNodeMap
中
1.2.5.3 Tree、Node、Context的关系
首先是这个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中的总体流量数据
1.2.5.4 InternalContextUtil#internalEnter
如果发现当前请求线程如果没有绑定
context
则给当前线程绑定一个名为sentinel_default_context
的context
1.2.5.5 SlotChainProvider#newSlotChain
- 首先根据当前资源从缓存中获取处理链
- 没有获取到则调用
SlotChainProvider#newSlotChain
构造处理链
1.2.5.6 CtSph#lookProcessChain(构造处理链)
- 这里首先通过
SPI方
式创建builder
如果你没有指定则会创建一个DefaultSlotChainBuilder
。
1.2.5.6 DefaultSlotChainBuilder#build
- 这里会创建一个
ProcessorSlotChain
- 通过
SPI
机制获取对应的处理链中的slot
,这里会去sentinel-core/src/main/resources/META-INF/services
找对应的Slot
然后进行初始化- 把
slot
添加到处理链中
1.2.5.7 DefaultProcessorSlotChain#entry
这里会调用到处理链中的具体的
slot
每个slot
的具体实现我们后续文章继续分析。