Sentinel 核心概念和工作流程详解

news2024/9/9 1:14:17

前言:

上一篇文章中,我们对 Sentinel 有了基本认知,知道其是 Alibaba 开源的一个服务稳定性组件,我们从 Sentinel 控制台认识了 Sentinel 的流控、降级、热点、授权规则,本篇我们将从核心概念和工作流程方面继续分析 Sentinel。

Sentinel 系列文章传送门:

Sentinel 初步认识及使用

Sentinel 两个核心概念

Sentinel 实现限流、隔离、降级、熔断等功能,其本质就是做了两件事情,统计数据和规则判断。

  • 统计数据:统计某个资源的访问数据,比如 QPS、RT、是否异常请求等。
  • 规则判断:判断限流规则、隔离规则、降级规则、熔断规则是否满足。

资源就是指被 Sentinel 保护的业务,例如项目中定义的 controlleer 方法就是默认被 Sentinel 保护的资源。

ProcessorSlotChain

Sentinel 实现试数据统计和规则判断的核心类是 ProcessorSlotChain,这个类基于责任链模式来设计,将不同的功能
封装为一个个的 Slot,请求进入后逐个执行即可,执行流程图如下:

在这里插入图片描述

图摘自 Github,Sentinel Github wiki 地址

Slot

数据统计 Slot(statistic)

  • NodeSelectorSlot:负责构建簇点链路中的节点(DefaultNode),将这些节点形成链路树。
  • ClusterBuilderSlot:负责构建某个资源的 ClusterNode,ClusterNoode 可以保存资源的运行信息(响应时间、QPS、block数目、线程数、异常数等)以及来源信息(origin名称)。
  • StatisticSlot:负责统计实时调用数据,包括运行信息、来源信息等。

规则判断 Slot(rulechecking)

  • AuthoritySlot:负责授权规则(来源控制)。
  • SystemSlot:负责系统保护规则。
  • ParamFlowSlot:负责热点参数限流规则。
  • FlowSlot:负责限流规则。
  • DegradeSlot:负责降级规则。

Context

Context 代表调用链路上下文,贯穿一次调用链路中的所有 Entry。Context 维持着入口节点(entranceNode)、本次调用链路的 curNode、调用来源(origin)等信息。Context 名称即为调用链路入口名称。Context 维持的方式:通过 ThreadLocal 传递,只有在入口 enter 的时候生效。由于 Context 是通过 ThreadLocal 传递的,因此对于异步调用链路,线程切换的时候会丢掉 Context,因此需要手动通过 ContextUtil.runOnContext(context, f) 来变换 context。

Entry

每一次资源调用都会创建一个 Entry。Entry 包含了资源名、curNode(当前统计节点)、originNode(来源统计节点)等信息。CtEntry 为普通的 Entry,在调用 SphU.entry(xxx) 的时候创建。特性:Linked entry within current context(内部维护着 parent 和 child)需要注意的一点:CtEntry 构造函数中会做调用链的变换,即将当前 Entry 接到传入 Context 的调用链路上(setUpEntryFor)。资源调用结束时需要 entry.exit()。exit 操作会过一遍 slot chain exit,恢复调用栈,exit context 然后清空 entry 中的 context 防止重复调用。

Node

Sentinel 里面的各种种类的统计节点:

  • StatisticNode:最为基础的统计节点,包含秒级和分钟级两个滑动窗口结构。
  • DefaultNode:链路节点,用于统计调用链路上某个资源的数据,维持树状结构。
  • ClusterNode:簇点,用于统计每个资源全局的数据(不区分调用链路),以及存放该资源的按来源区分的调用数据(类型为 StatisticNode)。特别地,Constants.ENTRY_NODE 节点用于统计全局的入口资源数据。
  • EntranceNode:入口节点,特殊的链路节点,对应某个 Context 入口的所有调用数据。Constants.ROOT 节点也是入口节点。

构建的时机:

  • EntranceNode 在 ContextUtil.enter(xxx) 的时候就创建了,然后塞到 Context 里面。
  • NodeSelectorSlot:根据 context 创建 DefaultNode,然后 set curNode to context。
  • ClusterBuilderSlot:首先根据 resourceName 创建 ClusterNode,并且 set clusterNode to defaultNode;然后再根据 origin 创建来源节点(类型为 StatisticNode),并且 set originNode to curEntry。

几种 Node 的维度(数目):

  • ClusterNode 的维度是 resource。
  • DefaultNode 的维度是 resource * context,存在每个 NodeSelectorSlot 的 map 里面。
  • EntranceNode 的维度是 context,存在 ContextUtil 类的 contextNameNodeMap 里面。
  • 来源节点(类型为 StatisticNode)的维度是 resource * origin,存在每个 ClusterNode 的 originCountMap 里面。

StatisticSlot

StatisticSlot 是 Sentinel 最为重要的类之一,用于根据规则判断结果进行相应的统计操作。entry 的时候:依次执行后面的判断 slot。每个 slot 触发流控的话会抛出异常(BlockException 的子类)。若有 BlockException 抛出,则记录 block 数据;若无异常抛出则算作可通过(pass),记录 pass 数据。exit 的时候:若无 error(无论是业务异常还是流控异常),记录 complete(success)以及 RT,线程数-1。记录数据的维度:线程数+1、记录当前 DefaultNode 数据、记录对应的 originNode 数据(若存在 origin)、累计 IN 统计数据(若流量类型为 IN)。

Sentinel 定义资源的两种方式

Sentinel 默认会将 Controller 中的方法作为被保护资源,我们来演示一下非 Controller 中方法被 Sentinel 保护的两种方式。

  1. 编码定义资源。

    编码模板如下:

private void sentinelTemplate() {
	//资源名 比如方法名、接口名或其它可唯一标识的字符串
	try (Entry entry = SphU.entry("resourceName")) {
		// 被保护的业务逻辑
	} catch (BlockException ex) {
		// 资源访问阻止,被限流或被降级
	}
}

编码定义资源演示

@GetMapping("/query-order-by-id")
public String queryOrderById(@RequestParam String orderId) {
	return orderService.queryOrderById(orderId);
}

@Override
public String queryOrderById(String orderId) {
	try (Entry ignored = SphU.entry("orderResouce")) {
		return "订单号:" + orderId;
	} catch (BlockException e) {
		log.error("异常信息:", e);
		return null;
	}
}

请求接口,Sentinel 控制台如下:

在这里插入图片描述
2. @SentinelResource 注解定义资源。

注解定义资源演示:

@SentinelResource(value = "sentinelResource")
@Override
public String testSentinelResource(String sentinelResource) {
	return "sentinelResource 测试:" + sentinelResource;
}

@GetMapping("/test-sentinel-resource")
public String testSentinelResource(@RequestParam String testSentinelResource) {
	return orderService.testSentinelResource(testSentinelResource);
}

注解演示结果:
在这里插入图片描述

@SentinelResource 注解的原理

我们上面演示了使用编码方式和注解方式都可以把资源交给 Sentinel 保护,编码方式容易理解,那注解方式下资源是怎么被 Sentinel 保护的呢?我们大胆猜测是否是使用 AOP 切面的方式实现的呢?我们通过搜索发现还真有一个叫做 SentinelResourceAspect 的类,如下:

@Aspect
public class SentinelResourceAspect extends AbstractSentinelAspectSupport {

    //切点 有 @SentinelResource 注解的方法
    @Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)")
    public void sentinelResourceAnnotationPointcut() {
    }

    @Around("sentinelResourceAnnotationPointcut()")
    public Object invokeResourceWithSentinel(ProceedingJoinPoint pjp) throws Throwable {
        //获取受保护的方法
        Method originMethod = resolveMethod(pjp);
        //获取注解
        SentinelResource annotation = originMethod.getAnnotation(SentinelResource.class);
        //注解为空判断
        if (annotation == null) {
            // Should not go through here.
            throw new IllegalStateException("Wrong state for SentinelResource annotation");
        }
        //获取资源名称 没有指定指定资源名称 则默认方法名称
        String resourceName = getResourceName(annotation.value(), originMethod);
        //获取 entry 类型
        EntryType entryType = annotation.entryType();
        //获取资源列席
        int resourceType = annotation.resourceType();
        Entry entry = null;
        try {
            //构造 entry 对象
            entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());
            //执行业务方法
            Object result = pjp.proceed();
            //返回
            return result;
        } catch (BlockException ex) {
            //异常处理
            return handleBlockException(pjp, annotation, ex);
        } catch (Throwable ex) {
            //异常处理
            Class<? extends Throwable>[] exceptionsToIgnore = annotation.exceptionsToIgnore();
            // The ignore list will be checked first.
            if (exceptionsToIgnore.length > 0 && exceptionBelongsTo(ex, exceptionsToIgnore)) {
                throw ex;
            }
            if (exceptionBelongsTo(ex, annotation.exceptionsToTrace())) {
                traceException(ex);
                return handleFallback(pjp, annotation, ex);
            }

            // No fallback function can handle the exception, so throw it out.
            throw ex;
        } finally {
            if (entry != null) {
                entry.exit(1, pjp.getArgs());
            }
        }
    }
}

通过 SentinelResourceAspect 类的源码可以知道 @SentinelResource 注解是一个标记,而 Sentinel 基于 AOP 思想,对被标记的方法做环绕增强,完成资源 Entry 的创建,实现了对资源的保护。

SentinelResourceAspect 类是何时加载的?

源码阅读的多了,不难想到去 Sentinel 的 META-INF/spring.properties 文件查看一下是否有相关类,spring.properties 如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.alibaba.cloud.sentinel.SentinelWebAutoConfiguration,\
com.alibaba.cloud.sentinel.SentinelWebFluxAutoConfiguration,\
com.alibaba.cloud.sentinel.endpoint.SentinelEndpointAutoConfiguration,\
com.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration,\
com.alibaba.cloud.sentinel.feign.SentinelFeignAutoConfiguration

org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\
com.alibaba.cloud.sentinel.custom.SentinelCircuitBreakerConfiguration

从 spring.properties 不难看出有 SentinelAutoConfiguration 类可能会更 SentinelResourceAspect 类的加载有关系,我们来验证一下。

果然在 SentinelAutoConfiguration 类中发现了一段定义 SentinelResourceAspect 的方法,如下:

@Bean
@ConditionalOnMissingBean
public SentinelResourceAspect sentinelResourceAspect() {
	return new SentinelResourceAspect();
}

至此 SentinelResourceAspect 类的加载时机已经很清楚了,SentinelAutoConfiguration 是 Spring Boot 自动装配的,而 SentinelAutoConfiguration 类中又定义了 SentinelResourceAspect 类。

欢迎提出建议及对错误的地方指出纠正。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

词的向量化和文本向量化

词的向量化和文本向量化 向量化one-hot编码提前准备词表不提前准备词表one-hot缺点 词向量简介词向量的定义和目标word embedding和word vector的区别onehot编码与词向量关系构建 训练方式1&#xff08;基于语言模型&#xff09;训练方式2&#xff08;基于窗口&#xff09;CBOW…

兴业法拍网周报|7月25日起,四大商业银行下调人民币存款利率

黄金地段&#xff1a;圣世一品潜藏团结湖公园对面&#xff0c;居身CBD复合都会核心区&#xff0c;咫尺央视新址&#xff0c;紧邻京广中心&#xff0c;毗邻国贸、嘉里中心、银泰中心、财富中心。 居住舒适&#xff1a;社区是2010年建成的新商品房社区&#xff0c;建筑风格现代简…

数据安全系统的定义与重要性

数据安全系统是指为数据处理系统建立和采用的技术和管理的安全保护机制&#xff0c;旨在保护计算机硬件、软件和数据不因偶然和恶意的原因遭到破坏、更改和泄露。数据安全系统在现代信息化社会中扮演着至关重要的角色&#xff0c;它确保了数据的完整性、可用性和保密性。以下是…

ShardingSphere实战(1)- 分库分表基础知识

一、为什么要分库分表 分库分表是一种数据库优化策略&#xff0c;主要用于解决大型应用或高并发场景下数据库性能瓶颈的问题。具体来说&#xff0c;分库分表可以带来以下好处&#xff1a; 提高性能&#xff1a; 减少单个数据库实例的负载&#xff0c;避免单点性能瓶颈。当数据…

【Linux从青铜到王者】tcp协议2

滑动窗口 滑动窗口是什么 上篇提到如果两端发送数据如果是一发一收那就是串行&#xff0c;效率很低&#xff0c;所以可以一次发送多个报文&#xff0c;一次也可以接受多个报文&#xff0c;可以大大的提高性能(其实是将多个段的等待时间重叠在一起了&#xff09; 那么是怎么发…

Golang | Leetcode Golang题解之第300题最长递增子序列

题目&#xff1a; 题解&#xff1a; func lengthOfLIS(nums []int) int {if len(nums)<1{return len(nums)}dp : make([]int,len(nums))for i:0;i<len(nums);i{dp[i]1}res : 1for i:1;i<len(nums);i{for j:0;j<i;j{if nums[i] > nums[j]{dp[i] max(dp[i],dp[j…

Java 沙漏图案(Hour-glass Pattern)

给定正整数 n&#xff0c;以沙漏形式打印数字模式。示例&#xff1a; 输入&#xff1a;rows_no 7 输出&#xff1a; 1 2 3 4 5 6 7 2 3 4 5 6 7 3 4 5 6 7 4 5 6 7 5 6 7 6 7 7 6 7 5 6 7 4 5 6 7 3 4 5 6 7 2 3 4 5 6 7 1 2 3 4 5 6…

物联网平台简介与选型

前言 什么是物联网&#xff1f; 简单解释&#xff1a;把你感兴趣的事物连接到网络。 阿里云定义&#xff1a;物联网&#xff08;Internet of Things&#xff0c;简称 IoT&#xff09;是指通过互联网连接和通信的物理设备和对象的网络。它是一个由传感器、软件和通信设备组成的…

Attribute Manipulation(属性编辑)、disentanglement(解纠缠)常用的两种做法:线性探针和PCA

解纠缠也对应于属性编辑&#xff0c;比如人脸的属性编辑&#xff0c;将人脸变微笑、变衰老&#xff0c;其中每一个属性变化也对应了一种有意义的latent direction 。想要应用这种direction可以分为两种方式&#xff1a;有监督的linear-probe&#xff08;线性探针&#xff09;和…

Logback 日志打印导致程序崩溃的实战分析

在软件开发和运维中&#xff0c;日志记录是必不可少的一环&#xff0c;帮我们追踪程序的行为&#xff0c;定位问题所在。然而&#xff0c;有时日志本身却可能成为问题的根源。本文将通过一个真实的案例来探讨 Logback 日志系统中的一个常见问题&#xff0c;当并发量大&#xff…

Vue.js常见指令

一、v-text与v-html v-text更新html元素的innerText v-html更新html元素的innerHtml 如果需要更新部分内容需要使用{{ }} 双括号差值表达式 案例&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title>VUE指令 …

python pip 错误 ModuleNotFoundError: No module named pip._internal 解决办法

问题 升级新版pip 之后,不论是本地,还是使用anaconda环境,都有可能在用pip下载的时候出现错误: ModuleNotFoundError: No module named pip._internal&#xff0c;我的电脑中存在好几个版本的Python。 解决办法&#xff1a; python -m ensurepip python -m pip install --upgr…

图片及色彩编码

1、日期类 ###年份 date_format(KaTeX parse error: Expected EOF, got # at position 14: 批售月份, %Y年) #̲##季度 (CASE WHEN…批售月份, ‘%m’) IN (1,2,3) THEN ‘1季度’ WHEN date_format( 批售月份 , ′ W H E N d a t e f o r m a t ( 批售月份, %m) IN (4,5,6) TH…

【鸿蒙踩坑记录】解决:tabs滑动时,第一个和最后一个页签回弹大问题

一、背景 tabs滑动切换时&#xff0c;第一个页签右滑回弹大&#xff0c;最后一个页签左滑回弹大&#xff0c;如何关闭回弹效果 二、问题展现 图1:第一个页签右滑时回弹较大 图2:最后一个页签左滑时回弹较大 预期&#xff1a;关闭回弹效果 三、实现思路 给第一个和最后一个…

项目负责人的高效会议策略:从准备到追踪

项目负责人的高效会议策略&#xff1a;从准备到追踪 前言一、会议低效的常见陷阱二、高效会议的准备策略三、会议实施的技巧四、会议追踪的重要性结语 前言 在项目管理的世界里&#xff0c;时间就是金钱&#xff0c;效率就是生命。作为项目负责人&#xff0c;我深刻体会到了会议…

Java网络编程----UDP实现单播,组播,广播

文章开头&#xff0c;先来回忆一下 什么是UDP&#xff1f; UDP 的全称是 User Datagram Protocol&#xff0c;用户数据报协议。它不需要所谓的握手操作&#xff0c;从而加快了通信速度&#xff0c;允许网络上的其他主机在接收方同意通信之前进行数据传输。 UDP 的特点主要有…

Python 教程(七):match...case 模式匹配

目录 专栏列表前言基本语法match 语句case 语句 模式匹配的类型示例具体值匹配类型匹配序列匹配星号表达式命名变量复杂匹配 模式匹配的优势总结 专栏列表 Python教程&#xff08;一&#xff09;&#xff1a;环境搭建及PyCharm安装Python 教程&#xff08;二&#xff09;&…

智能环保气膜网球馆:大空间与防雾霾的完美结合—轻空间

在现代都市生活中&#xff0c;空气质量和空间限制成为许多体育设施的挑战。气膜技术的出现&#xff0c;为这些问题提供了卓越的解决方案。我们的智能环保气膜网球馆&#xff0c;不仅拥有宽敞的空间&#xff0c;还具备卓越的防雾霾功能&#xff0c;为体育爱好者提供了一个理想的…

牧野电火花机床联网

一、找到可选项 选择主面板中的【可选项】按钮&#xff0c;弹出来的对话框如下图所示。 二、属性设定 在左下角部分找到【属性设定】&#xff0c;如序号一所示&#xff0c;在弹出的属性设定对话框中选中【牧野EDM服务器】&#xff0c;如下图所示。 三、选则MES模式 按照上图…

苹果推送iOS 18.1带来Apple Intelligence预览

&#x1f989; AI新闻 &#x1f680; 苹果推送iOS 18.1带来Apple Intelligence预览 摘要&#xff1a;苹果向iPhone和iPad用户推送iOS 18.1和iPadOS 18.1开发者预览版Beta更新&#xff0c;带来“Apple Intelligence”预览。目前仅支持M1芯片或更高版本的设备。Apple Intellige…