Sentine 源码分析之--AuthoritySlot、SystemSlot、GatewayFlowSlot

news2024/11/24 19:30:37

前言:

上一篇我对 Sentinel 中统计数据部分的 NodeSelectorSlot、ClusterBuilderSlot、StatisticSlot 的相关源码进行了分析,本篇我们开始分析规则相关的源码。

Sentinel 系列文章传送门:

Sentinel 初步认识及使用

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

Spring Cloud 整合 Nacos、Sentinel、OpenFigen 实战【微服务熔断降级实战】

Sentinel 源码分析入门【Entry、Chain、Context】

Sentine 源码分析之–NodeSelectorSlot、ClusterBuilderSlot、StatisticSlot

在这里插入图片描述

AuthoritySlot

关于 AuthoritySlot 官方是如下描述:

很多时候,我们需要根据调用来源来判断该次请求是否允许放行,这时候可以使用 Sentinel 的来源访问控制(黑白名单控制)的功能。来源访问控制根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。

AuthoritySlot 授权规则配置如下:
在这里插入图片描述

代码中的规则详情如下:
在这里插入图片描述

AuthoritySlot#entry 方法源码解析

AuthoritySlot#entry 方法还是老套路,执行一个校验方法,然后执行下一个 Sllot,重点关注校验方法。

//com.alibaba.csp.sentinel.slots.block.authority.AuthoritySlot#entry
@Override
public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, boolean prioritized, Object... args)
	throws Throwable {
	//检查黑白名单权限
	checkBlackWhiteAuthority(resourceWrapper, context);
	//进入下一个 slot
	fireEntry(context, resourceWrapper, node, count, prioritized, args);
}

AuthoritySlot#checkBlackWhiteAuthority 方法源码解析

AuthoritySlot#checkBlackWhiteAuthority 方法先是对规则和当前资源的规则进行为空判断,如果为空直接返回,否则循环遍历所有规则执行校验动作。

//com.alibaba.csp.sentinel.slots.block.authority.AuthoritySlot#checkBlackWhiteAuthority
void checkBlackWhiteAuthority(ResourceWrapper resource, Context context) throws AuthorityException {
	//获取所有权限规则
	Map<String, Set<AuthorityRule>> authorityRules = AuthorityRuleManager.getAuthorityRules();
	//authorityRules 为空判断
	if (authorityRules == null) {
		return;
	}
	//根据当前资源的 name 获取规则
	Set<AuthorityRule> rules = authorityRules.get(resource.getName());
	if (rules == null) {
		//规则为空 返回
		return;
	}
	//遍历所有规则
	for (AuthorityRule rule : rules) {
		//校验规则
		if (!AuthorityRuleChecker.passCheck(rule, context)) {
			//规则不通过直接抛出异常
			throw new AuthorityException(context.getOrigin(), rule);
		}
	}
}

ConfigCacheService#dumpBeta 方法源码解析

AuthorityRuleChecker#passCheck 方法主要做了一下几件事:

  • 对请求来源 orgin 和 黑白名单为空判断,如果为空则直接返回true,规则通过。
  • 判断请求来源是否在黑白名单中,如果在还会进行完全匹配,如果完全匹配也满足,就认为当前请求来源在黑白名单中。
  • 对规则策略进行判断,是黑名单类型且完全匹配到则返回规则不通过,是白名单类型且没有完全匹配到返回规则不通过,其他情况返回规则通过。

规则配置项解释如下:

  • resource:资源名,限流规则的作用对象。
  • limitApp:对应的黑白名单,不同 origin 用英文逗号分隔,如 app1,app2,app3。
  • strategy:规则策略,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式。

//com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleChecker#passCheck
static boolean passCheck(AuthorityRule rule, Context context) {
	//获取请求来源 orgin
	String requester = context.getOrigin();

	// Empty origin or empty limitApp will pass.
	//请求来源 orgin 为空 或者 对应的黑白名单为空  都直接返回
	if (StringUtil.isEmpty(requester) || StringUtil.isEmpty(rule.getLimitApp())) {
		return true;
	}

	// Do exact match with origin name.
	//getLimitApp 就是黑白名单 indexOf 判断 请求来源是否在 黑白名单中
	int pos = rule.getLimitApp().indexOf(requester);
	boolean contain = pos > -1;

	if (contain) {
		//在黑白名单中 还需要进一步判断
		boolean exactlyMatch = false;
		//黑白名单数组
		String[] appArray = rule.getLimitApp().split(",");
		for (String app : appArray) {
			//进行 equals 完全匹配
			if (requester.equals(app)) {
				//完全匹配到了
				exactlyMatch = true;
				//终止循环
				break;
			}
		}
		//完全匹配的值 赋值给 contain
		contain = exactlyMatch;
	}

	//获取规则策略 也就是 到底是黑明单  还是白名单
	int strategy = rule.getStrategy();
	if (strategy == RuleConstant.AUTHORITY_BLACK && contain) {
		//是黑名单 且完全匹配到了 返回 false
		return false;
	}

	if (strategy == RuleConstant.AUTHORITY_WHITE && !contain) {
		//是白名单 且没有完全匹配到 返回 false
		return false;
	}

	return true;
}

SystemSlot

SystemSlot 是系统级限流器。

SystemSlot 系统规则配置如下:
在这里插入图片描述

SystemSlot#entry 方法源码解析

SystemSlot#entry 方法同样是老套路,进行规则校验,执行下一个 Slot,我们重点关注规则校验。

//com.alibaba.csp.sentinel.slots.system.SystemSlot#entry
@Override
public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count,
				  boolean prioritized, Object... args) throws Throwable {
	//系统规则校验
	SystemRuleManager.checkSystem(resourceWrapper);
	//进入下一个 slot
	fireEntry(context, resourceWrapper, node, count, prioritized, args);
}

SystemRuleManager#checkSystem 方法源码解析

SystemRuleManager#checkSystem 方法主要做了如下几件事:

  • 校验资源是否为空。
  • 检查系统限流开关是否打开。
  • 对资源类型进行校验,系统限流只校验入口流量。
  • 对 QPS 、线程数和 maxRt 进行校验,如果大于系统阀值,则直接抛出异常。
  • 对 CPU 使用率和系统负载进行校验,如果大于系统阀值,则直接抛出异常。

//com.alibaba.csp.sentinel.slots.system.SystemRuleManager#checkSystem
public static void checkSystem(ResourceWrapper resourceWrapper) throws BlockException {
	//资源包装器为空判断
	if (resourceWrapper == null) {
		return;
	}
	// Ensure the checking switch is on.
	//检查开关是否打开 如果没有打开 直接返回
	if (!checkSystemStatus.get()) {
		return;
	}

	// for inbound traffic only
	//只对入口资源进行校验 其他资源直接返回
	if (resourceWrapper.getEntryType() != EntryType.IN) {
		return;
	}

	// total qps
	//获取 ClusterNode 记录的成功的 QPS
	double currentQps = Constants.ENTRY_NODE == null ? 0.0 : Constants.ENTRY_NODE.successQps();
	//判断是否大于 Double.MAX_VALUE 大于则抛出异常
	if (currentQps > qps) {
		throw new SystemBlockException(resourceWrapper.getName(), "qps");
	}

	// total thread
	//获取 ClusterNode 记录的 线程数
	int currentThread = Constants.ENTRY_NODE == null ? 0 : Constants.ENTRY_NODE.curThreadNum();
	//线程数大于 Long.MAX_VALUE 抛出异常
	if (currentThread > maxThread) {
		throw new SystemBlockException(resourceWrapper.getName(), "thread");
	}
	//获取 ClusterNode 记录的平均 rt
	double rt = Constants.ENTRY_NODE == null ? 0 : Constants.ENTRY_NODE.avgRt();
	//最大 rt 大于 Long.MAX_VALUE  抛出异常
	if (rt > maxRt) {
		throw new SystemBlockException(resourceWrapper.getName(), "rt");
	}

	// load. BBR algorithm.
	//全局系统负载校验
	//highestSystemLoadIsSet 默认 false
	//getCurrentSystemAvgLoad() 默认返回 -1
	//highestSystemLoad = Double.MAX_VALUE;
	//默认情况下是进入不了 if 的
	if (highestSystemLoadIsSet && getCurrentSystemAvgLoad() > highestSystemLoad) {
		if (!checkBbr(currentThread)) {
			throw new SystemBlockException(resourceWrapper.getName(), "load");
		}
	}

	// cpu usage
	//全局 CPU 校验
	//highestCpuUsageIsSet 默认 false
	//getCurrentCpuUsage() 默认返回 -1
	//highestCpuUsage = Double.MAX_VALUE;
	//默认情况下是进入不了 if 的
	if (highestCpuUsageIsSet && getCurrentCpuUsage() > highestCpuUsage) {
		throw new SystemBlockException(resourceWrapper.getName(), "cpu");
	}
}

SystemRuleManager#checkBbr 方法源码解析

SystemRuleManager#checkBbr 方法判断 ClusterNode 中记录的线程数大于系统最大负载则范湖规则不通过。

//com.alibaba.csp.sentinel.slots.system.SystemRuleManager#checkBbr
private static boolean checkBbr(int currentThread) {
	//currentThread ClusterNode 中记录的线程数
	if (currentThread > 1 &&
		currentThread > Constants.ENTRY_NODE.maxSuccessQps() * Constants.ENTRY_NODE.minRt() / 1000) {
		//ClusterNode 中记录的线程数 大于 请求成功的 QPS 乘以 最小 RT 除以 1000 得到的是系统最大负载
		//如果 线程数已经大于最大负载了 直接返回 false
		return false;
	}
	return true;
}

GatewayFlowSlot

Sentinel 支持 API 网关限流。

GatewayFlowSlot#entry 方法源码解析

GatewayFlowSlot#entry 方法只做了两件事,规则校验和进入下一个 Slot,我们重点关注规则校验。

//com.alibaba.csp.sentinel.adapter.gateway.common.slot.GatewayFlowSlot#entry
@Override
public void entry(Context context, ResourceWrapper resource, DefaultNode node, int count,
				  boolean prioritized, Object... args) throws Throwable {
	//检查网关参数 也就是规则校验
	checkGatewayParamFlow(resource, count, args);
	//进入下一个 slot
	fireEntry(context, resource, node, count, prioritized, args);
}

GatewayFlowSlot#checkGatewayParamFlow 方法源码解析

GatewayFlowSlot#checkGatewayParamFlow 方法首先对参数进行校验,如果参数为空则直接返回无需进行规则校验,否则获取规则对规则为空进行判断,如果规则不为空则执行规则校验,具体的规则校验我们会在在下一篇 ParamFlowSlot 中详细分析。

//com.alibaba.csp.sentinel.adapter.gateway.common.slot.GatewayFlowSlot#checkGatewayParamFlow
private void checkGatewayParamFlow(ResourceWrapper resourceWrapper, int count, Object... args)
	throws BlockException {
	//参数为空判断
	if (args == null) {
		return;
	}
	//获取参数规则
	List<ParamFlowRule> rules = GatewayRuleManager.getConvertedParamRules(resourceWrapper.getName());
	//规则为空判断
	if (rules == null || rules.isEmpty()) {
		return;
	}
	//遍历规则
	for (ParamFlowRule rule : rules) {
		// Initialize the parameter metrics.
		//初始化参数指标
		ParameterMetricStorage.initParamMetricsFor(resourceWrapper, rule);
		//执行规则校验
		if (!ParamFlowChecker.passCheck(resourceWrapper, rule, count, args)) {
			//校验不通过 抛出异常
			String triggeredParam = "";
			if (args.length > rule.getParamIdx()) {
				Object value = args[rule.getParamIdx()];
				triggeredParam = String.valueOf(value);
			}
			throw new ParamFlowException(resourceWrapper.getName(), triggeredParam, rule);
		}
	}
}

如有不正确的地方请各位指出纠正。

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

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

相关文章

国家机构选用NAS存储的要求是什么?

西北航天基地采用Infortrend NAS存储做影视后期及共享 国家机构航天基地每天都有升空任务&#xff0c;记录下的视频数据分发给对应的项目组的NAS存储设备上&#xff0c;方便每个项目组做分析总结、对外宣传及学术交流的使用需求&#xff0c;因此选用了Infortrend桌面级NAS存储…

数据采集器与条码扫描器的区别

在条码二维码的应用领域中&#xff0c;数据采集器和条码扫描器是其应用过程两种核心硬件设备&#xff0c;均具备独特的功能与应用场景&#xff0c;您是否真正了解数据采集器和条码扫描器之间的细微差别&#xff1f;这一区别对于您的项目开发成本和工作效率提升有着至关重要的影…

VM16中安装Linux虚拟机

VM16下安装Linux虚拟机 注意这里只安装虚拟机&#xff0c;并没有按照Linux操作系统&#xff0c;按装操作系统请看后续文章 点击“创建新的虚拟机” 选择自定义创建虚拟机 选择虚拟机的硬件兼容性 暂时不选择系统镜像文件我们选择稍后安装 选择操作系统类型和版本 命…

PEER:基于高效专家检索的Transformer模型扩展新方法

谷歌DeepMind提出了一种名为PEER的参数高效专家检索机制&#xff0c;利用产品密钥技术从超过百万个微型专家库中进行稀疏检索&#xff0c;从而提高模型效率和性能&#xff0c;有效解决了Transformer模型规模扩展带来的计算挑战。 论文介绍 在 Transformer 架构中&#xff0c;计…

ADC的一些细节2

一&#xff0c;转换时间 ADC 是挂载在 APB2 总线&#xff08;PCLK2&#xff09;上的&#xff0c;经过分频器得到 ADC 时钟&#xff08;ADCCLK&#xff09;&#xff0c;最高 14 MHz。 转换时间采样时间12.5个周期 12.5个周期是固定的&#xff0c;一般我们设置 PCLK272M&#x…

基于CentOS Stream 9平台搭建Nacos2.4.0.1集群,并使用OpenResty反向代理集群

目录展示 Nacos2.4.0.1集群搭建1. 下载2. 解压3.修改配置3.1分别修改下启动类中JDK路径以及启动大小3.2 分别配置数据源 修改端口去掉前面的#注释&#xff08;修改数据库地址、数据库用户名、密码&#xff09;If use MySQL as datasource:Count of DB:Connect URL of DB:密钥鉴…

空气质量传感器 - 从零开始认识各种传感器【第二十八期】

空气质量传感器|从零开始认识各种传感器 1、什么是空气质量传感器&#xff1f; 空气质量传感器是一种检测空气中污染物浓度的设备&#xff0c;广泛应用于环境监测、智能家居、工业控制和健康管理等领域。 2、空气质量传感器是如何工作的&#xff1f; 对于每个人都关心的空气质…

java学习day17MyBatis

Mybatis 数据持久化是将内存中的数据模型转换为存储模型&#xff0c;以及将存储模型转换为内存中数据模型的统称。例如&#xff0c;文件的存储、数据的读取以及对数据表的增删改查等都是数据持久化操作 MyBatis支持定制化SQL、存储过程以及高级映射&#xff0c;可以在实体类和…

【socket编程】预备知识 {IP地址和MAC地址;端口号;认识TCP/UDP协议;网络字节序;socket编程入门}

一、IP地址和MAC地址 源IP地址和目的IP地址 IP地址用于唯一标识网络中的一台主机在IP数据包头部中&#xff08;网络层&#xff09;, 有两个IP地址, 分别叫做源IP地址, 和目的IP地址这两个地址在网络传输过程中是不变的&#xff0c;因为它们是数据包的一部分&#xff0c;并且用…

Serverless 1

一、云原生应用 云原生应用覆盖到&#xff1a; 大数据&#xff0c;人工智能&#xff0c;边缘计算&#xff0c;区块链等 服务代理&#xff1a;envoy API 网关&#xff1a;APISIX 服务网格&#xff1a;Istio 服务发现&#xff1a;CoreDNS 消息和流式处理&#xff1a;kafka Serve…

打造高效校园办公:智慧校园行政办公合同类型

智慧校园行政办公中的合同类型功能是为了满足校园内各种合同管理需求而设计的一套数字化管理系统。该功能旨在提高合同管理效率&#xff0c;简化合同处理流程&#xff0c;确保合同内容的准确性和合规性。 智慧校园行政办公中的合同类型功能支持多种类型的合同管理&#xff0c;包…

【书生大模型实战营第三期 | 基础岛第1关-书生大模型全链路开源体系】

学习心得&#xff1a;《书生浦语大模型全链路开源开放体系》 摘要 通过观看哔哩哔哩上的《书生浦语大模型全链路开源开放体系》视频&#xff0c;我对开源大模型及其工具链有了更深入的了解。视频由社区贡献者汪周谦讲解&#xff0c;不仅介绍了书生浦语大模型的架构和功能&…

Excel公式与函数(运算符,计算限制,错误检查)(一)

公式 公式概念 公式 是以“”号为引导&#xff0c;用过运算符按照一定的顺序组合进行数据运算处理的等式&#xff0c;函数 则是按特定算法执行计算的产生一个或一组结果的预定义的特殊公式。 公式组成要素 公式的组成要素为“”&#xff0c;运算符&#xff0c;单元格引用&a…

基于STM32F407+NBIOT+华为云IOT平台设计的环境检测系统

基于STM32F407NBIOT华为云IOT平台设计的环境检测系统实现的功能&#xff1a; 【1】能够采集本地环境的温度、湿度、烟雾浓度&#xff0c;火光信息&#xff0c;在OLED显示屏上显示。 如果检测到烟雾、温度、火光超过阀值会触发蜂鸣器报警。 【2】能够通过NBIOT将本地设备采集的信…

LE-50821F/FA激光扫描传感器|360°避障雷达之性能参数与配置清单说明

LE系列激光扫描传感器|360避障雷达涵盖LE-50711、LE-50711F、​ LE-50621、LE-50821F、​LE-50621F、LE-50821FA、LE-50711FA、LE-50621FA等型号&#xff0c;广泛应用于自动化工厂、物流与仓储、汽车制造与物流、机械设备、能源与环境等领域的环境感知、高精度定位&#xff08;…

【dockerpython】亲测有效!适合新手!docker创建conda镜像+容器使用(挂载、端口映射、gpu使用)+云镜像仓库教程

文章目录 docker基本概念简介配置镜像加速源创建conda镜像1. 写 Dockerfile文件2. 创建镜像3. 创建容器并测试 容器的使用1. wsl挂载2. 端口映射3. 补充-gpu 云镜像仓库使用1. 登录2. 将本地镜像上传至云镜像仓库3. 从云镜像仓库下载镜像到本地 docker基本概念简介 简单来讲&a…

2024年“华数杯”数学竞赛A题完整解析 | 代码分享

机器臂关节角路径的优化设计 问题一 代码 Matlab clc clear % 参数定义 a [0, 300, 1200, 300, 0, 0]; alpha [0, -90, 0, -90, -90, -90]; d [600, 0, 0, 1200, 0, 0]; theta_min [-160, -150, -200, -180, -120, -180]; theta_max [160, 15, 80, 180, 120, 180]; P_t…

计算机网络(网络层)

网络层概述 网络层是干什么的&#xff1f; 网络层的主要任务是实现不同异构网络互连&#xff0c;进而实现数据包在各网络之间的传输相比于数据链路层的以太网通信&#xff0c;网络层则是将一个个数据链路层连接的以太网通过路由器连接起来。从而实现不同数据链路层的互联。 这…

【Linux】网络基础_3

文章目录 十、网络基础5. socket编程socket 常见APIsockaddr结构简单的UDP网络程序 未完待续 十、网络基础 5. socket编程 socket 常见API // 创建 socket 文件描述符 (TCP/UDP, 客户端 服务器) int socket(int domain, int type, int protocol);// 绑定端口号 (TCP/UDP, 服…

Ubuntu窗口如何自适应VM虚拟机

修改VM的显示设置 1&#xff1a;右击ubuntu计算机&#xff0c;点击设置按钮&#xff0c;进入到设置界面。 2&#xff1a;点击拉伸模式&#xff0c;选择自由拉伸。 以上操作结束之后打开ubuntu虚拟机。 ubuntu屏幕显示设置 进入到ubuntu系统之后&#xff0c;在桌面右击&…