Sentinel核心源码分析(上)
文章目录
- 前言
- 一、客户端与Spring Boot整合
- 二、SphU.entry
- 2.1、构建责任链
- 2.2、调用责任链
- 2.2.1、NodeSelectorSlot
- 2.2.2、ClusterBuilderSlot
- 2.2.3、LogSlot
- 2.2.4、StatisticSlot
- 2.2.5、AuthoritySlot
- 2.2.6、SystemSlot
- 2.2.7、FlowSlot
- 2.2.7.1、selectNodeByRequesterAndStrategy
- 2.2.7.2、canPass
- 2.2.8、DegradeSlot
- 总结
前言
Sentinel作为Spring cloud alibaba中流控的组件,在微服务架构中也有广泛的应用。其核心源码主要体现在客户端。客户端在启动时,和Nacos类似,也会将自己的信息注册到服务端。而服务端的页面上配置各种规则时,实际上也是将信息发送到了客户端。

我们最常使用的@SentinelResource注解:

底层也是基于AOP + 责任链模式实现的。**Sentinel的难点不在于处理流程,而在于限流的算法。**本篇仅介绍Sentinel责任链的核心流程。
一、客户端与Spring Boot整合
在Spring Boot项目中,如果需要引入Sentinel,通常需要在pom文件中加入:
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>
该组件也是利用了Spring Boot的自动配置:

其中的SentinelAutoConfiguration是核心:

在SentinelAutoConfiguration中,会注册SentinelResourceAspect Bean:

SentinelResourceAspect实际上是一个切面,匹配了所有加入了@SentinelResource注解的方法:

invokeResourceWithSentinel是一个环绕通知。。在执行目标方法之前,首先会得到目标方法对象,以及处理注解中的一些信息,然后调用SphU.entry方法。该方法是Sentinel流程的核心。

点击进去,会调用到entry方法:

Env在实例化之前,会触发static中的逻辑:

在doInit方法中,又会通过SPI机制,加载InitFunc中的类:


其中的HeartbeatSenderInitFunc是定期向服务端发送心跳的:


CommandCenterInitFunc,是将客户端各种接收规则的接口信息,暴露给服务端:

上面的逻辑,包括后续构建,执行责任链,是在切面中,并非是在应用启动时执行的,而是在执行加入了@SentinelResource注解的方法时才会去执行!
二、SphU.entry
SphU.entry方法内部主要做了两件事:
- 构建责任链。
- 按照顺序依次调用责任链。

2.1、构建责任链
在进入lookProcessChain方法后,首先通过双检锁模式,判断当前加入了@SentinelResource注解的方法,是否已经为其构建过责任链,如果没有,才会执行newSlotChain方法。也就是说,是每一个加入了注解的方法,都有一个对应的责任链,并且只在应用启动后该方法第一次被调用时初始化。

最终调用的是DefaultSlotChainBuilder的build方法:

在该方法中,主要做了两件事:

通过SPI机制,加载ProcessorSlots文件中的类(责任链中的具体组成类)。

真正地去构建责任链:在执行ProcessorSlotChain chain = new DefaultProcessorSlotChain();这一段代码时,实际上是构造了:

构造出的是下图的数据结构,end是指向first的引用:

在构造完成后,就会利用chain.addLast((AbstractLinkedProcessorSlot<?>) slot);方法,向上图的数据结构中插入具体的责任链类了:

首先将end的next指针指向NodeSelectorSlot,因为end是指向指向first的引用,实际上first的next指针也指向了NodeSelectorSlot:

然后将end指向NodeSelectorSlot:

以此类推,最终构建出的责任链是:

图片来源:图灵学院
2.2、调用责任链
这里我们重点关注FlowSlot和DegradeSlot,它们是sentinel核心功能-限流熔断降级的体现。
2.2.1、NodeSelectorSlot
首先调用的是NodeSelectorSlot,它的作用是构建资源调用的统计节点,用于记录调用链路信息,并且将资源关联到相应的 DefaultNode。

fireEntry就是在满足条件的情况下,继续调用后续的责任链。
2.2.2、ClusterBuilderSlot
ClusterBuilderSlot和NodeSelectorSlot是类似的,它的作用是构建统计节点的聚合关系。但是NodeSelectorSlot 是按调用链统计,ClusterBuilderSlot 是按资源维度统计。

2.2.3、LogSlot
LogSlot的作用,是在后续的责任链调用过程中出现异常时,进行日志的记录,体现在它的try…catch中:

2.2.4、StatisticSlot
StatisticSlot是先将请求放行到后续的责任链,在后续的责任链调用完成后,再去进行统计资源的调用情况的操作。例如记录 QPS(每秒请求数)、RT(响应时间)、线程数、异常数等。

包括抛出了各种异常之后的记录,这些记录都是执行降级、限流等控制的基础数据来源。

2.2.5、AuthoritySlot
AuthoritySlot是进行授权规则的检查,例如黑白名单:

简单回顾一下黑白名单的使用,首先需要在sentinel控制台的授权规则选项卡进行配置:

这里的资源名,是http请求的路径,而流控应用,可以是特定的ip,也可以是请求路径:
@Component
public class IPLimiter implements RequestOriginParser {/*** 获取当前服务实例的ip*/@Overridepublic String parseOrigin(HttpServletRequest httpServletRequest) {return httpServletRequest.getRemoteAddr();}
}
在checkBlackWhiteAuthority方法中,首先会获取所有设置的规则,然后根据当前的资源名,获取该资源对应的所有规则

然后进行检查:

这里的黑白名单体现在RuleConstant这个常量类中:

判断逻辑有点绕:
- 如果规则中的IP或路径,和请求中的匹配,contain会为true,反之为false。
- 在黑名单的判定中,如果contain为true,则返回false,代表请求不通过。因为黑名单就是要对能和规则匹配上的请求进行拦截。
- 在白名单的判断中,如果contain为false,则返回false,代表请求不通过。因为contain为false,代表请求和规则匹配不上,也就是不在白名单中。

2.2.6、SystemSlot
SystemSlot是对系统规则进行控制,包括系统整体的 QPS,平均响应时间(RT),当前系统的并发线程数等。


2.2.7、FlowSlot
FlowSlot是 Sentinel 的核心功能之一,用于流量控制(限流)规则判断。

同样会获取到控制台设置的所有规则,然后逐个进行匹配:

最终调用到的是passLocalCheck,其中也有两个关键方法:

2.2.7.1、selectNodeByRequesterAndStrategy
selectNodeByRequesterAndStrategy用于在执行限流时 选择哪个节点(Node)来做统计和判断。不同的来源(origin)和限流策略(strategy)决定了限流数据统计的维度。首先会获取到流控模式,也就是控制台设置的:

- 匹配指定 origin 的限流
- 如果是
直接模式,就利用context.getOriginNode();调用方自己的统计节点限流。 - 如果是其他策略,利用
selectReferenceNode再次匹配:
- 如果是

- 如果来源是
default:- 直接限流时,使用当前资源的全局统计节点
- 非直接限流,使用关联资源的统计节点。
- 如果来源是
other:- 直接限流时,使用当前资源的全局统计节点
- 非直接限流,使用关联资源的统计节点。
2.2.7.2、canPass
在拿到上一步推断出的节点后,会调用canPass方法,这里的canPass也有不同的实现:

对应控制台中的:

这里涉及到滑动窗口,令牌桶,漏桶算法,会在后续进行说明。 Sentinel的难点不在于流程,而是算法。
2.2.8、DegradeSlot
DegradeSlot的作用是熔断降级控制。也是 Sentinel 的核心功能之一:
在tryPass方法中,会对逐条规则进行校验,如果此时的断路器处于打开状态,

并且超过了熔断时间,会修改状态为半开。

熔断降级中有一个重要的概念,也就是断路器。在Sentinel 1.8 版本之后,断路器有三种状态,都记录在CircuitBreaker的内部State枚举类中:
在这里简单的说一下三种状态的转换:
- 正常情况下,断路器处于
关闭状态,所有请求正常通过。 - 当请求触发了降级条件(如异常比例过高、RT过大) 后,断路器会进入
打开状态,在接下来的熔断时长内(如 10 秒),所有请求都被拒绝(降级)。 - 当熔断时长结束后,下一个请求到达时,断路器进入
半开状态:- 如果该请求再次触发降级条件,断路器重新回到
打开状态。 - 如果该请求通过且正常,断路器会恢复为
关闭状态。
- 如果该请求再次触发降级条件,断路器重新回到
Closed → [触发降级条件] → Open → [熔断时长结束,下一请求] → Half-Open
↑ ↓
└────── [探测失败] ←──── [探测成功] ←──────────────┘
总结
本篇介绍了Sentinel 实现控制台功能,在服务端的实现原理:通过AOP + 责任链模式实现。并且在调用目标方法时,为每一个请求都创建一份责任链,放入缓存,依次调用。
后面几个责任链的实现,在规则校验不通过时,都会抛出异常,而真正处理的逻辑,在StatisticSlot的catch中,以及SentinelResourceAspect#invokeResourceWithSentinel的entry.exit中,包括处理断路器的状态。
下一篇:Sentinel核心源码分析(下)
相关文章:
Sentinel核心源码分析(上)
文章目录 前言一、客户端与Spring Boot整合二、SphU.entry2.1、构建责任链2.2、调用责任链2.2.1、NodeSelectorSlot2.2.2、ClusterBuilderSlot2.2.3、LogSlot2.2.4、StatisticSlot2.2.5、AuthoritySlot2.2.6、SystemSlot2.2.7、FlowSlot2.2.7.1、selectNodeByRequesterAndStrat…...
Systemd安全加密备份系统与智能通知
实训背景 你是一家金融科技公司的系统架构师,需为敏感数据设计一套安全备份系统,满足以下需求: 加密存储:自动解密插入的LUKS加密USB设备,挂载到安全目录。备份验证:备份完成后校验文件完整性,…...
6.0 使用Qt+ OpenCV+Python加载图片
本例作为python图像处理的入门课程1,使用Qt+ OpenCV+Python加载图片。 主要有如下几个地方需要注意: 1. OpenCV 默认使用 BGR 格式,而 Qt 使用 RGB。显示前需要转换:cv2.cvtColor(img, cv2.COLOR_BGR2RGB),一般使用某个QLabel控件进行显示。 pic = cv2.cvtColor(pic, cv2.C…...
深度学习篇---网络分析(1)
文章目录 前言1. ImprovedResBlock(改进的残差块)结构组成卷积层1卷积层2跳跃连接(Downsample) 前向传播流程主路径跳跃路径残差连接 2. EnhancedCNN(主模型)2.1 初始特征提取层功能参数变化 2.2 残差块堆叠…...
【Mac 从 0 到 1 保姆级配置教程 11】- Mac 基础配置 Finder、触控板、常用快捷键等
文章目录 前言配置 Finder1. 把我们的家目录请出来2. 显示文件扩展名3. 展示隐藏文件4. 显示路径栏和状态栏5. 固定文件夹到工具栏 基础快捷键1. Finder 导航快捷键2. 文件操作快捷键3. 视图和显示快捷键4. 搜索和选择快捷键5. 实用技巧6. 关于文件创建 配置触控板1. 右键设置2…...
C++Primer - 动态内存管理
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...
DeepSeek本地部署(Ollama)
1. Ollama 安装 Ollama 官网地址: https://ollama.com/安装包网盘地址: https://pan.baidu.com 2. Deepseek 部署 根据自己电脑配置和应用需求选择不同模型,配置不足会导致运行时候卡顿。 版本安装指令模型大小硬盘(存储)显卡…...
Amodal3R ,南洋理工推出的 3D 生成模型
Amodal3R 是一款先进的条件式 3D 生成模型,能够从部分可见的 2D 物体图像中推断并重建完整的 3D 结构与外观。该模型建立在基础的 3D 生成模型 TRELLIS 之上,通过引入掩码加权多头交叉注意力机制与遮挡感知注意力层,利用遮挡先验知识优化重建…...
第二期:深入理解 Spring Web MVC [特殊字符](核心注解 + 进阶开发)
前言: 欢迎来到 Spring Web MVC 深入学习 的第二期!在第一期中,我们介绍了 Spring Web MVC 的基础知识,学习了如何 搭建开发环境、配置 Spring MVC、编写第一个应用,并初步了解了 控制器、视图解析、请求处理流程 等核…...
论伺服电机在轨道式巡检机器人中的优势及应用实践
一、引言 1.1 研究背景与意义 在现代工业生产、电力系统、轨道交通等诸多领域,保障设施设备的安全稳定运行至关重要。轨道式巡检机器人作为一种高效、智能的巡检工具,正逐渐在这些领域崭露头角。它能够沿着预设轨道,对目标区域进行全方位…...
开源软件与自由软件:一场理念与实践的交锋
在科技的世界里,“开源软件”和“自由软件”这两个词几乎无人不知。很多人或许都听说过,它们的代码是公开的,可以供所有人查看、修改和使用。然而,若要细究它们之间的区别,恐怕不少朋友会觉得云里雾里。今天࿰…...
(51单片机)独立按键控制流水灯LED流向(独立按键教程)(LED使用教程)
源代码 如上图将7个文放在Keli5 中即可,然后烧录在单片机中就行了 烧录软件用的是STC-ISP,不知道怎么安装的可以去看江科大的视频: 【51单片机入门教程-2020版 程序全程纯手打 从零开始入门】https://www.bilibili.com/video/BV1Mb411e7re?…...
开发指南111-关闭所有打开的子窗口
门户系统是通过window.open通过单点登录的模式打开子系统的,这就要求门户系统退出时,关闭所有打开的子系统。 平台处理这一问题的核心原理如下: 主窗口定义: allChildWindows:[], //所有子窗口 pushChildWindow(childWindow){ …...
react-router children路由报错
项目场景: 写个路由页面,引发的问题 问题描述 报错: An absolute child route path must start with the combined path of all its parent routes. 代码: import { createBrowserRouter } from "react-router-dom";…...
双向链表示例
#include <stdio.h> #include <stdlib.h>// 定义双向链表节点结构体 typedef struct list {int data; // 数据部分struct list *next; // 指向下一个节点的指针struct list *prev; // 指向前一个节点的指针 } list_t;// 初始化链表,将链表的…...
Socket编程TCP
Socket编程TCP 1、V1——EchoServer单进程版2、V2——EchoServer多进程版3、V3——EchoServer多线程版4、V4——EchoServer线程池版5、V5——多线程远程命令执行6、验证TCP——Windows作为client访问Linux7、connect的断线重连 1、V1——EchoServer单进程版 在TcpServer.hpp中实…...
当网页受到DDOS网络攻击有哪些应对方法?
分布式拒绝服务攻击也是人们较为熟悉的DDOS攻击,这类攻击会通过大量受控制的僵尸网络向目标服务器发送请求,以此来消耗服务器中的资源,致使用户无法正常访问,当网页受到分布式拒绝服务攻击时都有哪些应对方法呢? 建立全…...
文件映射mmap与管道文件
在用户态申请内存,内存内容和磁盘内容建立一一映射 读写内存等价于读写磁盘 支持随机访问 简单来说,把磁盘里的数据与内存的用户态建立一一映射关系,让读写内存等价于读写磁盘,支持随机访问。 管道文件:进程间通信机…...
4.4刷题记录(哈希表)
1.242. 有效的字母异位词 - 力扣(LeetCode) class Solution { public:bool isAnagram(string s, string t) {unordered_map<char,int>cnt_s,cnt_t;for(int i0;i<s.size();i){cnt_s[s[i]];}for(int i0;i<t.size();i){cnt_t[t[i]];}if(cnt_sc…...
代码随想录回溯算法03
93.复原IP地址 本期本来是很有难度的,不过 大家做完 分割回文串 之后,本题就容易很多了 题目链接/文章讲解:代码随想录 视频讲解:回溯算法如何分割字符串并判断是合法IP?| LeetCode:93.复原IP地址_哔哩哔…...
批量改CAD图层颜色——CAD c#二次开发
一个文件夹下大量图纸(几百甚至几千个文件)需要改图层颜色时,可采用插件实现,效果如下: 转换前: 转换后: 使用方式如下:netload加载此dll插件,输入xx运行。 附部分代码如…...
【内网安全】DHCP 饿死攻击和防护
正常情况:PC2可以正常获取到DHCP SERVER分别的IP地址查看DHCP SERCER 的ip pool地址池可以看到分配了一个地址、Total 253个 Used 1个 使用kali工具进行模拟攻击 进行DHCP DISCOVER攻击 此时查看DHCP SERVER d大量的抓包:大量的DHCP Discover包 此时模…...
【愚公系列】《高效使用DeepSeek》055-可靠性评估与提升
🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! 👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"…...
AI时代编程教育启示录:为什么基础原理依然不可或缺?
李升伟 编译 在生成式AI重塑编程教育的今天,我作为拥有十年开发者关系团队管理经验、编程训练营教学经历的专业软件工程师,想与大家探讨这个新时代的编程教育之道。 平衡之道:基础原理与AI工具的博弈 当GitHub Copilot、Amazon Q Deve…...
10种电阻综合对比——《器件手册--电阻》
二、电阻 前言 10种电阻对比数据表 电阻类型 原理 特点 应用 贴片电阻 贴片电阻是表面贴装元件,通过将电阻体直接贴在电路板上实现电路连接 体积小、重量轻,适合高密度电路板;精度高、稳定性好,便于自动化生产 广泛应用于…...
剑指Offer(数据结构与算法面试题精讲)C++版——day6
剑指Offer(数据结构与算法面试题精讲)C版——day6 题目一:不含重复字符的最长子字符串题目二:包含所有字符的最短字符串题目三:有效的回文 题目一:不含重复字符的最长子字符串 这里还是可以使用前面&#x…...
freertos韦东山---事件组以及实验
事件组的原理是什么,有哪些优点,为啥要创造出这个概念 在实时操作系统(如 FreeRTOS)中,事件组是一种用于任务间同步和通信的机制,它的原理、优点及存在意义如下: 事件组原理 数据结构…...
架构师面试(二十六):系统拆分
问题 今天我们聊电商系统实际业务场景的问题,考查对业务系统问题的分析能力、解决问题的能力和对系统长期发展的整体规划能力。 一电商平台在早期阶段业务发展迅速,DAU在 10W;整个电商系统按水平分层架构进行设计,包括【入口网关…...
Spring 中的事务
🧾 一、什么是事务? 🧠 通俗理解: 事务 一组操作,要么全部成功,要么全部失败,不能只做一半。 比如你转账: A 账户扣钱B 账户加钱 如果 A 扣了钱但 B 没收到,那就出问…...
Java中的同步和异步
一、前言 在Java中,同步(Synchronous)和异步(Asynchronous)是两种不同的任务处理模式。核心区别在任务执行的顺序控制和线程阻塞行为。 二、同步(Synchronous) 定义:任务按顺序执行…...
