Sentinel核心源码解析
Sentinel是分布式系统的防御系统。以流量为切入点,通过动态设置的流量控制、服务熔断等手段达到
保护系统的目的,通过服务降级增强服务被拒后用户的体验。
一、Sentinel工作原理
1 架构图解析
若要读懂Sentinel源码,则必须要搞明白官方给出的Sentinel的架构图。
微服务框架核心源码深度解析<<大厂学院完结>>

Sentinel的核心骨架是ProcessorSlotChain。其将不同的 Slot 按照顺序串在一起(责任链模式),从而将不同的功能组合在一起(限流、降级、系统保护)。系统会为每个资源创建一套SlotChain。
2 SPI机制
Sentinel槽链中各Slot的执行顺序是固定好的。但并不是绝对不能改变的。Sentinel将ProcessorSlot 作为 SPI 接口进行扩展,使得 SlotChain 具备了扩展能力。用户可以自定义Slot并编排Slot 间的顺序。

3 Slot简介
NodeSelectorSlot
负责收集资源的路径,并将这些资源的调用路径,以树状结构存储起来,用于根据调用路径来限流降。
ClusterBuilderSlot
用于存储资源的统计信息以及调用者信息,例如该资源的 RT, QPS, thread count,Block count,Exception count 等等,这些信息将用作为多维度限流,降级的依据。简单来说,就是用于构建ClusterNode。
StatisticSlot
用于记录、统计不同纬度的 runtime 指标监控信息。
ParamFlowSlot
对应热点流控。
FlowSlot
用于根据预设的限流规则以及前面 slot 统计的状态,来进行流量控制。对应流控规则。
AuthoritySlot
根据配置的黑白名单和调用来源信息,来做黑白名单控制。对应授权规则。
DegradeSlot
通过统计信息以及预设的规则,来做熔断降级。对应降级规则。
SystemSlot
通过系统的状态,例如 load1 等,来控制总的入口流量。对应系统规则。
4 Context简介
Context是对资源操作的上下文,每个资源操作必须属于一个Context。如果代码中没有指定Context,则会创建一个name为sentinel_default_context的默认Context。一个Context生命周期中可以包含多个资源操作。Context生命周期中的最后一个资源在exit()时会清理该Conetxt,这也就意味着这个Context生命周期结束了。
5 Context代码
// 创建一个来自于appA访问的Context, // entranceOne为Context的name ContextUtil.enter("entranceOne", "appA"); // Entry就是一个资源操作对象 Entry resource1 = null; Entry resource2 = null; try { // 获取资源resource1的entry resource1 = SphU.entry("resource1"); // 代码能走到这里,说明当前对资源resource1的请求通过了流控 // 对资源resource1的相关业务处理。。。 // 获取资源resource2的entry resource2 = SphU.entry("resource2"); // 代码能走到这里,说明当前对资源resource2的请求通过了流控 // 对资源resource2的相关业务处理。。。 } catch (BlockException e) { // 代码能走到这里,说明请求被限流, // 这里执行降级处理 } finally { if (resource1 != null) { resource1.exit(); } if (resource2 != null) { resource2.exit(); } } // 释放Context ContextUtil.exit(); // --------------------------------------------------------
// 创建另一个来自于appA访问的Context, // entranceTwo为Context的name ContextUtil.enter("entranceTwo", "appA"); // Entry就是一个资源操作对象 Entry resource3 = null; try { // 获取资源resource2的entry resource2 = SphU.entry("resource2"); // 代码能走到这里,说明当前对资源resource2的请求通过了流控 // 对资源resource2的相关业务处理。。。 // 获取资源resource3的entry resource3 = SphU.entry("resource3"); // 代码能走到这里,说明当前对资源resource3的请求通过了流控 // 对资源resource3的相关业务处理。。。 } catch (BlockException e) { // 代码能走到这里,说明请求被限流, // 这里执行降级处理 } finally { if (resource2 != null) { resource2.exit(); } if (resource3 != null) { resource3.exit(); } } // 释放Context ContextUtil.exit();
6 Node间的

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