欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > Sentine 源码分析之--AuthoritySlot、SystemSlot、GatewayFlowSlot

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

2024/10/24 22:31:09 来源:https://blog.csdn.net/weixin_42118323/article/details/140737897  浏览:    关键词:Sentine 源码分析之--AuthoritySlot、SystemSlot、GatewayFlowSlot

前言:

上一篇我对 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);//进入下一个 slotfireEntry(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) {//获取请求来源 orginString 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;}}//完全匹配的值 赋值给 containcontain = exactlyMatch;}//获取规则策略 也就是 到底是黑明单  还是白名单int strategy = rule.getStrategy();if (strategy == RuleConstant.AUTHORITY_BLACK && contain) {//是黑名单 且完全匹配到了 返回 falsereturn false;}if (strategy == RuleConstant.AUTHORITY_WHITE && !contain) {//是白名单 且没有完全匹配到 返回 falsereturn 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);//进入下一个 slotfireEntry(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 记录的成功的 QPSdouble 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 记录的平均 rtdouble 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 得到的是系统最大负载//如果 线程数已经大于最大负载了 直接返回 falsereturn 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);//进入下一个 slotfireEntry(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);}}
}

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com