Sentinel源码二:责任链

本文详细解读了Sentinel框架的各个模块,包括适配器、基准测试、集群流控、核心限流模块,以及如何在SpringMVC示例中实现限流。重点介绍了Node、Context和CtEntry的概念及其在限流处理中的作用。流程总结了从入口点到执行保护策略的完整过程。
摘要由CSDN通过智能技术生成

源码模块

image.png

  • sentinel-adapter:适配器模块,主要实现了对一些常用框架的适配
  • sentinel-benchmark:基准测试模块,对核心代码的精确性提供基准测试
  • sentinel-cluster:集群流控,主要是负责sentinel集群流控相关功能的
  • sentinel-core:限流核心模块,限流、降级、熔断等功能都在这里实现
  • sentinel-demo:样例模块,可以参考怎么使用sentinel进行限流、降级
  • sentinel-extension扩展模块,主要对DataSource进行了部分拓展实现
  • sentinel-loggin:拓展模块,主要是对DataSource进行了部分拓展实现
  • sentinel-transport:传输模块,提供了基本的监控服务端和客户端的APi接口,以及一些基于不同库的实现(Http和Netty)

Node、Context、CtEntry讲解

在源码分析前还是讲一下Node、Context、CtEntry的逻辑,后面会大量的用到
当属于同一个应用下的请求过来后,会首先判断是否有Root,没有的话就会新建一个Root节点。 再往下就会出现EntranceNode、DefaultNode、CLusterNode三种node,那这三种节点又是什么关系呢?我们首先看一下这三个节点类的关系图:
image.png
其中StatsticNode是用作数据统计的,那根据继承关系其他三个Node也是进行数据统计的,那么它们分别的作用是什么那?在讲这三个Node前,大家要明白Sentinel的几个核心概念Context、资源操作符CtEntry:

  • Context:对资源操作的上下文,里面包含EntranceNode(入口节点),如果代码中没有指定context,则会创建一个name为sentinel_default_context的默认context。一个Context生命周期可以包含多个资源操作CtEntry。Context生命周期中的最后一个资源在exit时会清理Context
  • CtEntry:它会保存一次资源访问链路元数据和该资源所对应的实时信息,每个资源操作都必须属于一个Context

接下来就是三个节点:
image.png

  • StatisticNode:统计节点,是Node接口的实现类,用于完成数据统计
  • EntranceNode:入口节点,一个Context会有一个入口节点,用于统计当前Context的总体流量数据
  • DefaultNode:默认节点,用于统计一个资源在当前Context中的流量数据
  • ClusterNode:集群节点,用于统计一个资源在所有Context中的总体流量数据 而Sentinel也是通过滑动窗口算法高效的实现数据统计

这些逻辑后面代码都会体现,需要认真看

入口

这里选用demo模块下面的sentinel-demo-transport-spring-mvc来看sentinel是如何做限流的
image.png

entry = SphU.entry(“demo-hello-api”)

image.png
在获取sph这个静态属性的时候,会调用静态方法

Env.sph

image.png

InitExecutor.doInit():
image.png
这里一共做了两件事:

  1. 通过Spi机制 获取所有InitFunc的类,并且排序
  2. 调用它们的init去加载资源,其中不同的initFun分别有:
    • CommandCenterInitFunc:用于初始化所有CommandCenter,对外提供客户端的数据处理功能
    • DefaultClusterClientInitFunc:用于初始化集群限流客户端的所需资源
    • DefaultClusterServerInitFunc:用于初始化集群限流服务端的所需资源
    • ParamFlowStatisticSlotCallbackInit:用于初始化参数流控回调

CtSph.entry

image.png
image.png
总结一下这里做了哪些事:

  1. 获取上下文Context
  2. 使用责任链创建功能插槽
  3. 走责任链对资源对象进行限流等操作

ContextUtil.getContext()

先看ContextUtil的静态代码:
image.png
主要做了这些事:

  1. 创建了一个EntranceNode(入口节点)

image.png

  1. 通过Constants.Root创建一个root节点,然后将创建的node节点加入到root的子节点中

image.png

  1. 存入到contextNameNodeMap

这里并没有创建context,只是创建Node,并且把name和Node放到一个map中

InternalContextUtil.internalEnter

image.png
image.png

  1. 在获取上下文时,首先会从线程中获取到Context,或获取到就直接返回
  2. 如果是线程首次获取,则为空;然后会根据context的名称去缓存中去找表示入口的节点EntranceNode,如果Entrancenode为空则会通过一个双重检测锁的机制创建一个EntranceNode,然后会将Context对象中的入口节点设置为新创建的 EntranceNode。最后将context对象存入到ThreadLocal中。

这里才会真正的创建Context,并且设置Node、Origin,并且把它放到ThreadLocal

lookProcessChain(resourceWrapper)

image.png
如果chainMap没有chain,那就创建一个:
SlotChainProvider.newSlotChain():
image.png
slotChainBuilder.build():
image.png
这里会根据META-INF/services/com.alibaba.csp.sentinel.slotchain.ProcessorSlot读取到ProcessorSlot文件内存进行初始化,然后把它们放到一个责任链中
image.png
�构建出来的chain链:
image.png

new CtEntry(resourceWrapper, chain, context, count, args)

�创建资源操作对象
image.png

chain.entry(context, resourceWrapper, null, count, prioritized, args)

image.png
开始链式调用了

NodeSelectorSlot

这个 Slot 会选择或创建相应的 Node(节点),以便其他 Slot 可以针对这些节点进行统计和控制。
image.png
在执行完这段代码之后:
context里面的entranceNode(入口节点)会在它的childList新建一个Node节点:
image.png

ctEntry里面的curNode会设置为当前节点:
image.png

最终会形成这样:
image.png

ClusterBuilderSlot

image.png
这个node节点是上面创建的DefaultNode,会设置它的clusterNode
image.png

最终形成:
image.png

LogSlot

在执行保护策略或流量控制逻辑时记录相关的日志,便于监控和故障诊断。
image.png

StatisticSlot

收集和维护资源(如 API 调用)的运行时指标,如 QPS、线程数、响应时间等
image.png
会继续往后面调用,最终在去统计�

AuthoritySlot

检查请求是否有权访问某资源,基于黑名单或白名单进行访问控制。
image.png

SystemSlot

根据系统的负载情况(如 CPU 使用率、总体 QPS、平均响应时间等)动态调整流量入口,以防止系统过载。
image.png

FlowSlot

�实现流量控制规则,如 QPS 控制、并发线程数控制等,防止资源被过度使用
image.png
checkFlow()源码:
这里就是去判断指定资源的流控规则是否能够正常通过,若不能通过则抛出异常,被限流了。且后续不再应用。其中canPassCheck就是进行详细判断的方法。方法具体的获取实时流量数据并进行判断的相关源码请参考后续集群流控源码分析
image.png

DefaultCircuitBreakerSlot

当资源的运行状况低于预设的阈值时,自动切断对该资源的访问,经过一段时间后再尝试恢复,以防止系统雪崩�

image.png

DegradeSlot

根据资源的运行状态(如异常比例、响应时间)动态地进行降级操作,如返回一个默认值或抛出异常,以保护系统稳定运行�
image.png

总结

sentinel限流处理流程如下:
image.png

  • 26
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值