sentinel核心流程源码解析

sentinel的处理槽(ProcessorSlot)

可以说,sentinel实现的各种功能就是由各处理槽完成的 ,ProcessorSlot定义了四个方法:

当进入该处理槽时触发该方法

处理完 entry方法之后触发该方法

退出该处理槽时触发该方法

exit方法处理完成时触发该方法

 sentinel的核心处理槽

 其中:FlowSlot是处理流控规则的处理槽,DegradeSlot是处理降级规则的处理槽。。。。以此类推

sentinel的处理槽链---DefaultProcessorSlotChain

 

从 DefaultProcessorSlotChain类继承图上和构造器上看,DefaultProcessorSlotChain使用装饰器模式在内部构造了一个AbstractLinkedProcessorSlot的单向链表

同时查看AbstractLinkedProcessorSlot的相关代码可以发现:

 AbstractLinkedProcessorSlot实现了两个fire方法,均是触发自身关联的下一个节点(Slot)的相关动作

以上是关于sentinel核心流程的最核心源码知识储备,有了以上基础之后,我们开始最核心的流程源码分析,请记住:sentinel的各种功能是由各个slot完成的,DefaultProcessorSlotChain是一个由AbstractLinkedProcessorSlot组成的单项链表,AbstractLinkednProcessorSlot的两个fire方法均是触发自身关联的下个slot的对应方法调用

sentinel的数据装载容器Node

看一下sentinel的Node类继承图:

 Node只有一个直接子类:StatisticNode,其他的node均是StatisticNode的直接子类或者间接子类

Node中定义了各种数据统计的接口方法:

 重头戏:StatisticNode

首先看一下类属性:

在StatisticNode中有2个关键的 ArrayMetric,是数据统计的关键

ArrayMetric的属性截图如下:

 ArrayMetric有个关键属性

LeapArray<MetricBucket> data = new OccupiableBucketLeapArray(sampleCount, intervalInMs);

这个在上一篇关于sentinel---滑动窗口的实现原理_昱宸星光的博客-CSDN博客有专门分析过。

所以到现在为止可以这样理解:

StatisticNode对象包含属性:ArrayMetric,而ArrayMetric对象包含:LeapArray<MetricBucket>对象,也就是说:StatisticNode可以通过LeapArray的滑动窗口数据统计特性完成数据收集,进而完成数据统计的功能

从一段简单的代码开始

以上代码就是sentinel实现限流的最简单的demo。源码分析就从这里开始:

FlowRule的类继承图:

 FlowRule定义的属性:

private int grade = RuleConstant.FLOW_GRADE_QPS; // 限流类型,默认是QPSprivate double count; // 限流阈值
private int strategy = RuleConstant.STRATEGY_DIRECT; // 限流策略 默认是直接抛异常

以上是几个关键的属性

FlowRuleManager#loadRules 做了哪些操作

 从类源码上看,FlowManager定义了一个Map,存储的是资源名和FlowRule列表的映射

还有一个FlowPropertyListener流控规则监听器

还有一个SentinelProperty对象,并且在SentinelProperty对象上添加了监听器FlowPropertyListener

SentinelProperty是DynamicSentinelProperty子类,DynamicSentinelProperty对象当属性变化时会调用监听器对象

所以:

当FlowManager#loadRules时,

 会调用DynamicSentinelProperty#updateValue

 最终会调用到FlowPropertyListener的ConfigUpdate方法完成规则的装载

 此时:flowRules会构建出一个:资源名和限流规则列表的映射map

SphU.entry("AddUser") 源码跟踪

 SphU#entry调用到Env.sph.entry

 相当于最终是由CtSph#entry完成功能,当然这里还有一段static静态代码块,静态代码块完成的功能等到后面再揭晓!继续往下

代码一路跟踪,最后到达:CtSph#entryWithPriority方法:

 

 从entryWithPriority方法看:

1 首先构造一个Context上下文

2 构建处理槽链

3 进入处理槽链处理逻辑

先看核心逻辑:构建处理槽链

通过SlotChainProvider#newSlotChain完成处理槽链的生成,然后放入到一个map中

SlotChainProvider#newSlotChain

 这里通过sentinel的SPI机制完成默认SlotChainBuilder的加载,默认情况下回返回:DefaultSlotChainBuilder的实例,最终会调用DefaultSlotChainBuilder#build会构建一个DefaultProcessorSlotChain返回,再前面的基础知识储备已经说过,DefaultProcessorSlotChain包含一个AbstractLinkedProcessSlot的单项链表,是后续sentinel各种功能的核心基础

 

通过调试,发现此时通过SPI机制,将各功能的Slot均实例化出来,形成一个单项链表

 到这里,sentinel的主流核心逻辑基本已经分析完毕。

即:通过SPI机制,将各功能的SLot构建成一个单向链表,后续在做请求时,依次经过该带向链表做各自规则的判断,如果触发相应的规则,就抛出:BlockException

 其中:FlowException、DegradeException、AuthorityException、SystemBlockException均是BlockException的子类

各Slot的核心功能源码分析

FlowSlot:流控规则处理槽

 是否限流委托给了checker#checkFlow做判断

最终的限流逻辑是交由: TrafficShapingController#canPass判断的

 这个TrafficShapingController是FlowRule里面的一个属性,在之前通过FlowRuleManager构建资源和规则列表时,有提到默认是创建的DefaultController类

查看DefaultController#canPass方法

 从代码逻辑上看,最核心的计算由方法avgUsedTokens(node)计算得出,而该方法既是取node中已有的数据?那node的数据又是从哪里来的呢?一路追踪,在之前的DefaultProcessorSlotChain中会构建一个slot链表,其中有个StatisticSlot。这个slot就是专门做数据统计的,看下StatisticSlot

的代码:

 StatisticSlot是一个关于统计的slot,先触发后续slot的调用,如果能成功返回到该方法,说明后续的处理没有抛出异常,就把成功数和总数都+count,如果在后续的slot处理过程中抛出异常,会被该slot捕获,根据捕获的异常不同做不同的逻辑处理

 到这里,似乎sentinel限流、降级、熔断等功能的实现逻辑都已经完全梳理清楚了。但是:

有个疑问:不管是限流还是降级熔断等,均是在一个时间段内统计数据,而StatisticSlot在统计的时候是通过node加数据完成的,那node和时间单位是怎么联系起来的?换句话说:StatisticSlot里面的node是怎么做到在把数据按照单位时间统计的,而且后续代码在取数据时也是取到该时间单位内的数据的?

在上面说DefaultProcessorSlotChain时,忽略了部分细节,通过调试,我们发现构建的DefaultProcessorSlotChain的单向链表的顺序是:

1 NodeSelectorSlot   2 ClusterBuilderSlot  3 StatisticSlot  4 AuthoritySlot 

5 SystemSlot  6 FlowSlot  7 DegradeSlot 

跟踪代码调用逻辑,在StatisticSlot中通过node.pass()统计通过的数据,而此处的Node是ClusterNode,而ClusterNode是StatisticNode的直接子类。在上面的基础知识储备中有提到:StatisticNode通过属性ArrayMetric->LeapArray完成滑动窗口统计数据。换句话说:StatisticSlot通过StatisticNode完成滑动窗口统计数据,包括:通过数据,异常数据,总数据等等

至此:流控规则的完整调用链路,逻辑已全部梳理完成

sentinel通过构建DefaultProcessorSlotChain将全部的slot组装成一个单项链表,链表顺序是:

NodeSelectorSlot --》ClusterBuilderSlot -》StatisticSlot -》AuthoritySlot 

-》SystemSlot-》FlowSlot-》DegradeSlot

在FlowSlot中处理限流逻辑,限流是通过Slot中的StatisticNode做滑动窗口计数统计完成。而计数统计发生在StatisticSlot中 

以上就是通过分析限流规则梳理的Sentinel的核心流程,在此过程中还遗留了不少细节方面的未关注处理。

如果感兴趣的同学可以自行跟踪DegradSlot的处理流程完成降级规则的处理逻辑梳理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/88542.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

枚举缓存工具

此文章为笔记&#xff0c;为阅读其他文章的感受、补充、记录、练习、汇总&#xff0c;非原创&#xff0c;感谢每个知识分享者。 文章目录 1. 背景2. 枚举缓存3. 样例展示4. 性能对比5. 总结 本文通过几种样例展示如何高效优雅的使用java枚举消除冗余代码。 1. 背景 枚举在系统…

一文读懂HTML

文章目录 HTML的历史HTML的作用HTML的基本语言 HTML的历史 HTML&#xff08;HyperText Markup Language&#xff09;的历史可以追溯到20世纪90年代早期&#xff0c;它是互联网发展的重要里程碑之一。以下是HTML的历史概述&#xff1a; 早期阶段&#xff08;1980年代末 - 1990年…

创新引领城市进化:人工智能和大数据塑造智慧城市新面貌

人工智能和大数据等前沿技术正以惊人的速度融入智慧城市的方方面面&#xff0c;为城市的发展注入了强大的智慧和活力。这些技术的应用不仅令城市管理更高效、居民生活更便捷&#xff0c;还为可持续发展和创新奠定了坚实的基础。 在智慧城市中&#xff0c;人工智能技术正成为城市…

Unity使用C# Protobuf源码

目录 第一步&#xff1a;下载源码 第二步&#xff1a;运行C#构建文件 第三步&#xff1a;处理报错&#xff08;如果你已安装对应的SDK则不会报错&#xff09; 第四步&#xff1a;复制库文件到你的工程 第一步&#xff1a;下载源码 protobuf github源码https://github.com/p…

《甲午》观后感——GPT-3.5所写

《甲午》是一部令人深思的纪录片&#xff0c;通过生动的画面和真实的故事&#xff0c;向观众展示了中国历史上的一段重要时期。观看这部纪录片&#xff0c;我深受触动&#xff0c;对历史的认识也得到了深化。 首先&#xff0c;这部纪录片通过精心搜集的历史资料和珍贵的影像资料…

Xamarin.Android实现手写板的功能

目录 1、背景说明2、实现效果3、代码实现3.1 整体思路3.2 核心绘画类-PaintView.cs3.3 对话框类-WritePadDialog.cs3.4 前端实现类-MainActivity3.5 布局文件3.5.1 write_pad.xml3.5.2 activity_main布局文件 4、知识总结5、代码下载6、参考资料 1、背景说明 在实际使用过程中…

vector的模拟实现

什么是vector vector是一个封装了动态大小数组的顺序容器跟任意其它类型容器一样&#xff0c;它能够存放各种类型的对象。 模拟实现 实现前的准备 在实现vector之前&#xff0c;为了和库里的区分开需要将实现的vector放在一个自定义的命名空间里。而且vector需要实现成模版…

ITIL4—度量和报告实践

1. 关于本文 本文为度量和报告实践提供了实用指南&#xff0c;分为五个主要部分&#xff0c;涵盖&#xff1a; 本实践的基本信息本实践相关的流程和活动&#xff0c;及其在服务价值链中的作用参与本实践的组织和人员支持本实践的信息和技术合作伙伴和供应商在本实践中的注意事…

P1123 取数游戏

取数游戏 题目描述 一个 N M N\times M NM 的由非负整数构成的数字矩阵&#xff0c;你需要在其中取出若干个数字&#xff0c;使得取出的任意两个数字不相邻&#xff08;若一个数字在另外一个数字相邻 8 8 8 个格子中的一个即认为这两个数字相邻&#xff09;&#xff0c;求…

React源码解析18(1)------ React.createElement 和 jsx

1.React.createElement 我们知道在React17版本之前&#xff0c;我们在项目中是一定需要引入react的。 import React from “react” 即便我们有时候没有使用到React&#xff0c;也需要引入。原因是什么呢&#xff1f; 在React项目中&#xff0c;如果我们使用了模板语法JSX&am…

性能测试—Jmeter工具

文章目录 性能测试1. 术语介绍2. 方法3. 应用场景4. 工具&#xff08;Jmeter&#xff09;4.1 介绍4.2 元件和组件4.2.2 元件4.2.1 组件 4.3 作用域4.4 参数化4.5 执行脚本 性能测试 1. 术语介绍 响应时间(Response time)&#xff1a;对请求作出响应所需要的时间。 在互联网上对…

小型双轮差速底盘机器人实现红外跟随功能

1. 功能说明 本文示例将实现R023样机小型双轮差速底盘跟随人移动的功能。在小型双轮差速底盘前方按下图所示安装3个 近红外传感器&#xff0c;制作一个红外线发射源&#xff0c;实现当红外发射源在机器人的检测范围内任意放置或移动时&#xff0c;机器人能追踪该发射源。 2. 电…

数学建模学习(10):遗传算法

遗传算法简介 • 遗传算法&#xff08;Genetic Algorithms&#xff09;是基于生物进化理论的原理发展起来的一种广为 应用的、高效的随机搜索与优化的方法。其主要特点是群体搜索策略和群体中个体之 间的信息交换&#xff0c;搜索不依赖于梯度信息。它是20世纪70年代初期由美国…

数据结构--栈和队列

文章目录 栈的概念和结构栈的实现栈的数据结构栈的初始化和销毁出栈和入栈获取栈顶、大小&#xff0c;判空 队列的概念和结构队列的实现队列的数据结构队列的初始化和销毁队列的插入 队列的删除获取队头和队尾的数据获取队列长度和判空 栈和队列的一些题目1.有效的括号2.用队列…

【Leetcode】155. 最小栈、JZ31 栈的压入、弹出序列

作者&#xff1a;小卢 专栏&#xff1a;《Leetcode》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 155. 最小栈 155. 最小栈 题目描述; 设计一个支持 push &#xff0c;pop &#xff0c;top …

【配置环境】Linux下安装MySQL

目录 一&#xff0c;环境 二&#xff0c;安装步骤 1.使用包管理器安装MySQL 2.配置MySQL的安全选项 3.设置root用户使用密码进行身份验证&#xff08;可选&#xff09; 三&#xff0c;拓展知识 1.如何修改MySQL的密码策略&#xff1f; 2.实现连接MySQL数据库的测试代码…

docker基础

安装docker 参考安装&#xff1a; https://docs.docker.com/engine/install/centos/#installation-methods 开机启动 systemctl enable docker.service systemctl is-enabled docker.service 安装docker compose https://github.com/docker/compose/releases/tag/v2.17.2 …

Idea报错:Cannot resolve symbol “springframework“以及各种依赖包

问题描述&#xff1a; Idea导入了maven项目之后出现报错Cannot resolve symbol “springframework” &#xff0c;识别不了这个标识或者找不到这个包&#xff0c;明明这些依赖和包都有就是出现报错&#xff0c;并且运行按钮变成灰色 解决办法&#xff1a; 其实这个原因大概率就…

【rust/egui】(二)看看template的main函数:日志输出以及eframe run_native

说在前面 rust新手&#xff0c;egui没啥找到啥教程&#xff0c;这里自己记录下学习过程环境&#xff1a;windows11 22H2rust版本&#xff1a;rustc 1.71.1egui版本&#xff1a;0.22.0eframe版本&#xff1a;0.22.0上一篇&#xff1a;这里 开始 首先让我们看看main.rs中有些什么…

【Linux系统编程】21.echo、env、fork、getpid、getppid

目录 echo PATH SHELL TERM LANG HOME env fork 返回值 getpid getppid 测试代码1 测试结果 测试代码2 测试结果 父子进程相同 父子进程不同 父子进程共享 echo 查看单个环境变量。 PATH 可执行文件的搜索路径。 SHELL 当前Shell。 TERM 当前终端类型。终端…