引言
在分析Sentinel的上一篇文章中,我们知道了它是基于滑动窗口做的流量统计,那么在当我们能够根据流量统计算法拿到流量的实时数据后,下一步要做的事情自然就是基于这些数据做流控。在介绍Sentinel的流控模型之前,我们先来简单看下 Sentinel 后台是如何去定义一个流控规则的
image.png
对于上图的配置Sentinel把它抽象成一个FlowRule类,与其属性一一对应
resource 资源名
limitApp 限流来源,默认为default不区分来源
grade 限流类型,有QPS和并发线程数两种类型
count 限流阈值
strategy 流控策略 1. 直接 2. 关联 3.链路
controlBehavior 流控效果 1.快速失败 2.预热启动 3.排队等待 4. 预热启动排队等待
warmUpPeriodSec 流控效果为预热启动时的预热时长(秒)
maxQueueingTimeMs 流控效果为排队等待时的等待时长 (毫秒)
下面我们来看下选择流控策略和流控效果的核心代码
private static boolean passLocalCheck(FlowRule rule, Context context, DefaultNode node, int acquireCount,boolean prioritized) {
// 根据流控策略选择需要流控的Node维度节点
Node selectedNode = selectNodeByRequesterAndStrategy(rule, context, node);
if (selectedNode == null) {
return true;
}
// 获取配置的流控效果 控制器 (1. 直接拒绝 2. 预热启动 3. 排队 4. 预热启动排队等待)
return rule.getRater().canPass(selectedNode, acquireCount, prioritized);
}
上面的代码比较简单流程也很清晰,首先根据我们配置的流控策略获取到合适维度的 Node 节点(Node节点是Sentinel做流量统计的基本单位),然后再获取到规则中配置的流控效果控制器(1. 直接拒绝 2. 预热启动 3. 排队等待 4.预热启动排队等待)。
流控策略
下面我们来看下选择流控策略的源码分析
static Node selectNodeByRequesterAndStrategy(/*@NonNull*/ FlowRule rule, Context context, DefaultNode node) {
// 获取限流来源 limitApp
String limitApp = rule.getLimitApp();
// 获取限流策略
int strategy = rule.getStrategy();
// 获取当前 上下文的 来源
String origin = context.getOrigin();
// 如果规则配置的限流来源 limitApp 等于 当前上下文来源
if (limitApp.equals(origin) && filterOrigin(origin)) {
// 且配置的流控策略是 直接关联策略
if (strategy == RuleConstant.STRATEGY_DIRECT) {
// 直接返回当前来源 origin 节点
return context.getOriginNode();
}
// 配置的策略为关联或则链路
return selectReferenceNode(rule, context, node);
// 如果规则配置的限流来源 limitApp 等于 default
} else if (RuleConstant.LIMIT_APP_DEFAULT.equals(limitApp)) {
// 且配置的流控策略是 直接关联策略
if (strategy == RuleConstant.STRATEGY_DIRECT) {
// 直接返回当前资源的 clusterNode
return node.getClusterNode();
}
// 配置的策略为关联或则链路
return selectReferenceNode(rule, context, node);
// 如果规则配置的限流来源 limitApp 等于 other,且当前上下文origin不在流控规则策略中
} else if (RuleConstant.LIMIT_APP_OTHER.equals(limitApp)
&& FlowRuleManager.isOtherOrigin(origin, rule.getResource())) {
// 且配置的流控策略是 直接关联策略
if