Sentinel源码分析
Sentinel的基本概念
Sentinel实现限流、隔离、降级、熔断等功能,本质是做了两件事:
- 统计数据:统计某资源访问数据(QPS、RT等)。
- 规则判断:判断限流规则时、隔离规则、降级规则、熔断规则是否满足。
这里的资源就是希望被Sentinel保护的业务,如项目中Controller方法就是默认被Sentinel保护的资源。
ProcessorSlotChain
Sentinel 的核心骨架,将不同的 Slot 按照顺序串在一起(责任链模式),从而将不同的功能(限流、降级、系统保护)组合在一起。slot chain 其实可以分为两部分:统计数据构建部分(statistic)和判断部分(rule checking)。核心结构:
责任链中的slot也分为两大类:
- 统计数据构建部分(statistic)
- NodeSelectorSlot:负责构建簇点链路中的节点(DefaultNode),将这些节点形成链路树
- ClusterBuilderSlot:负责构建某个资源的ClusterNode,ClusterNode可以保存资源的运行信息(响应时间、QPS、block数据、线程数、异常数等)以及来源信息(origin名称)
- StatisticSlot:负责统计实时调用数据,包括运行信息、来源信息等
- 规则判断部分(rule checking)
- AuthoritySlot:负责授权规则(来源控制)
- SystemSlot:负责系统保护规则
- ParamFlowSlot:负责热点参数限流规则
- FlowSlot:负责限流规则
- DegradeSlot:负责降级规则
Node
Sentinel 里面的各种种类的统计节点:
所有的节点都可以记录对资源的访问统计数据,所以都是StatisticNode的子类。
按照作用分为两类Node:
- DefaultNode:代表链路树中的每个资源,一个资源出现在不同的链路中时,会创建不同的DefaultNode节点。而树的入口节点叫EntranceNode,是一种特殊的DefaultNode
- ClusterNode:代表资源,一个资源不管出现在多少个链路中,只会有一个ClusterNode。记录的是当前资源被访问的所有数据之和。
DefaultNode记录的是资源在当前链路中的访问数据,用来实现基于链路模式的先流规则。ClusterNode记录的是资源的所有链路的访问数据,实现默认模式、关联模式的先流规则。
例如:造一个MVC项目中,有两个业务:
- 业务1:controller中的资源/order/query访问service中的资源/goods
- 业务2:controller中的资源/order/save访问service中的资源/goods
创建的链路图如下:
Entry
默认情况下,Sentinel会将Controller中的方法作为被保护的资源,如果要将自己的代码标记为Sentinel的资源,则需要声明Entry,示例如下:
- 引入依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
- 配置Sentinel地址
spring: cloud: sentinel: transport: dashboard: localhost:8080
- 编写代码
try (Entry login = SphU.entry("login")) { // 业务代码 } catch (BlockException e) { return "被限流"; }
- 注解方式实现:
@SentinelResource注解基于AOP思想,对加注解的方法进行环绕增强,完成资源(Entry)的创建。@SentinelResource("login")
Context
进入控制台我们发现,簇点链路中除了我们写的方法节点外,还有一个默认sentinel_spring_web_context节点,这是一个EntranceNode类型的节点,在初始化Context的时候有Sentinel创建的。
什么是Context
- Context代表调用链路的上下文,贯穿一次调用链路中的所有资源(Entry),基于ThreadLocal实现。
- Context维持着入口节点(EntraceNode)、本次调用链路的curNode(当前资源节点)、调用来源(origin)等信息。
- 后续的Slot都可以通过Context拿到DefaultNode或者ClusterNode,从而获取统计数据,完成规则判断。
- Context初始化的过程中,会创建EntraceNode、contextName就是EntraceNode的名称
对应API如下:
ContextUtil.entry("contextName", "originName");
Context初始化
自动装配 spring.factories声明需要自动装配的类
首先我们看SentinelWebAutoConfiguration类:
AbstractSentinelInterceptor
ContextUtil
ProcessorSlotChain执行流程
入口
回到入口,AbstractSentinelInterceptor类的preHandle方法(见上图);以及SentinelResourceAspect的环绕增强方法:
可以看到,任何资源必须执行SphU.entry()方法,我们跟踪此方法找到真实创建的方法:
DefaultProcessorSlotChain
NodeSelectorSlot
NodeSelectorSlot负责构建簇点链路中的节点(DefaultNode),将这些节点形成链路树
ClusterBuilderSlot
ClusterBuilderSlot 负责构建某个资源的ClusterNode
LogSlot
除了记录异常日志外,啥都没干
StatisticSlot
StatisticSlot负责统计调用数据,包含访问次数、线程数、来源信息等。
StatisticSlot是实现限流的关键,基于滑动时间窗口算法维护计数器来统计进入某个资源的请求次数,用于后面的降级限流使用。
AuthoritySlot
根据黑白名单和来源来判断是否授权
SystemSlot
ParamFlowSlot
FlowSlot
滑动时间窗口(预热或直接拒绝)
滑动时间窗口算法这里用的是一个环形数组来统计当前时间窗口的QPS数据,比如每个窗口时间为1s,将窗口分割为2个区间,则每个区间时间间隔为500ms,当窗口区间分割越多,统计数据越精确,但复杂度越高。
漏桶(排队等候)
让所有请求进入队列中,再根据阈值设置的时间间隔依次放行。流量稳定,起到流量削峰的作用。但如果等待时间超出最大等待时常,说明流量过载,直接拒绝。
DegradeSlot
前面我们讲过降级机制是基于状态机制实现的:
- 本文标签: spring sentinel 微服务
- 本文链接: https://www.58cto.cn/article/3
- 版权声明: 本文由程序言原创发布, 非商业性可自由转载、引用,但需署名作者且注明文章出处:程序言 》 Sentinel源码分析 - https://www.58cto.cn/article/3