4.Sentinel源码分析— Sentinel是如何做到降级的?

4.Sentinel源码分析— Sentinel是如何到降级的?

各位中秋节快乐啊,我觉得在这个月圆之夜有必要写一篇源码解析,以表示我内心的高兴~

Sentinel源码解析系列:
1.Sentinel源码分析—FlowRuleManager加载规则了什么?

2. Sentinel源码分析—Sentinel是如何进行流量统计的?

3. Sentinel源码分析— QPS流量控制是如何实现的?

在我的第二篇文章里面2. Sentinel源码分析—Sentinel是如何进行流量统计的?里面介绍了整个Sentinel的主流程是怎样的。所以降级的大致流程可以概述为:
1. 设置降级策略,是根据平均响应时间还是异常比例来进行降级的
2. 根据资源创建一系列的插槽
3. 依次调用插槽,根据设定的插槽类型来进行降级

我们先来看个例子,方便大家自己断点跟踪:

private static final String KEY = "abc"; private static final int threadCount = 100; private static int seconds = 60 + 40; public static void main(String[] args) throws Exception { List<DegradeRule> rules = new ArrayList<DegradeRule>(); DegradeRule rule = new DegradeRule(); rule.setResource(KEY); // set threshold rt, 10 ms rule.setCount(10); rule.setGrade(RuleConstant.DEGRADE_GRADE_RT); rule.setTimeWindow(10); rules.add(rule); DegradeRuleManager.loadRules(rules); for (int i = 0; i < threadCount; i++) { Thread entryThread = new Thread(new Runnable() { @Override public void run() { while (true) { Entry entry = null; try { TimeUnit.MILLISECONDS.sleep(5); entry = SphU.entry(KEY); // token acquired pass.incrementAndGet(); // sleep 600 ms, as rt TimeUnit.MILLISECONDS.sleep(600); } catch (Exception e) { block.incrementAndGet(); } finally { total.incrementAndGet(); if (entry != null) { entry.exit(); } } } } }); entryThread.setName("working-thread"); entryThread.start(); } }

其他的流程基本上和第二篇文章里介绍的差不多,这篇文章来介绍Sentinel的主流程,Sentinel的降级策略全部都是在DegradeSlot中进行操作的。

DegradeSlot

public class DegradeSlot extends AbstractLinkedProcessorSlot<DefaultNode> { @Override public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, boolean prioritized, Object... args) throws Throwable { DegradeRuleManager.checkDegrade(resourceWrapper, context, node, count); fireEntry(context, resourceWrapper, node, count, prioritized, args); } }

DegradeSlot会直接调用DegradeRuleManager进行降级的操作,我们直接进入到DegradeRuleManager.checkDegrade方法中。

DegradeRuleManager#checkDegrade

public static void checkDegrade(ResourceWrapper resource, Context context, DefaultNode node, int count) throws BlockException { //根据resource来获取降级策略 Set<DegradeRule> rules = degradeRules.get(resource.getName()); if (rules == null) { return; } for (DegradeRule rule : rules) { if (!rule.passCheck(context, node, count)) { throw new DegradeException(rule.getLimitApp(), rule); } } }

这个方法逻辑也是非常的清晰,首先是根据资源名获取到注册过的降级规则,然后遍历规则集合调用规则的passCheck,如果返回false那么就抛出异常进行降级。

DegradeRule#passCheck

public boolean passCheck(Context context, DefaultNode node, int acquireCount, Object... args) { //返回false直接进行降级 if (cut.get()) { return false; } //降级是根据资源的全局节点来进行判断降级策略的 ClusterNode clusterNode = ClusterBuilderSlot.getClusterNode(this.getResource()); if (clusterNode == null) { return true; } //根据响应时间降级策略 if (grade == RuleConstant.DEGRADE_GRADE_RT) { //获取节点的平均响应时间 double rt = clusterNode.avgRt(); if (rt < this.count) { passCount.set(0); return true; } //rtSlowRequestAmount默认是5 // Sentinel will degrade the service only if count exceeds. if (passCount.incrementAndGet() < rtSlowRequestAmount) { return true; } // 根据异常比例降级 } else if (grade == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) { double exception = clusterNode.exceptionQps(); double success = clusterNode.successQps(); double total = clusterNode.totalQps(); // If total amount is less than minRequestAmount, the request will pass. if (total < minRequestAmount) { return true; } // In the same aligned statistic time window, // "success" (aka. completed count) = exception count + non-exception count (realSuccess) double realSuccess = success - exception; if (realSuccess <= 0 && exception < minRequestAmount) { return true; } if (exception / success < count) { return true; } // 根据异常数降级 } else if (grade == RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) { double exception = clusterNode.totalException(); if (exception < count) { return true; } } //根据设置的时间窗口进行重置 if (cut.compareAndSet(false, true)) { ResetTask resetTask = new ResetTask(this); pool.schedule(resetTask, timeWindow, TimeUnit.SECONDS); } return false; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zydpsp.html