我是靠谱客的博主 超级羊,这篇文章主要介绍流控神器Sentinel指南:熔断降级源码分析,现在分享给大家,希望可以做个参考。

Sentinel 熔断降级(后面简称为降级)会在调用链路中某个资源出现不稳定状态时,例如调用超时或异常比例升高,对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都抛出 DegradeException。

Sentinel的降级检测在DegradeSlot中:

复制代码
1
2
3
4
5
6
7
8
9
10
11
@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); } @Override public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) { fireExit(context, resourceWrapper, count, args); }

这里通过DegradeRuleManager来判断是否熔断。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void checkDegrade(ResourceWrapper resource, Context context, DefaultNode node, int count) throws BlockException { // degradeRules保存了所有的熔断规则,key为ResourceName,value为 Set<DegradeRule> 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); } } }

取出熔断规则对象后,逐个遍历,调用了DegradeRule的paseCheck方法,如果过不通过抛出DegradeException异常。

DegradeRule中重要的成员变量如下:

复制代码
1
2
3
4
5
6
7
8
private int grade private double count; private int timeWindow; private final AtomicBoolean cut = new AtomicBoolean(false); private AtomicLong passCount = new AtomicLong(0); private static ScheduledExecutorService pool = Executors.newScheduledThreadPool( Runtime.getRuntime().availableProcessors(), new NamedThreadFactory("sentinel-degrade-reset-task", true));
  • grade为熔断的策略,分别可以为rt(一秒内平均响应时间)、异常比例(1秒内)、异常数。

  • count对应上面三种策略

  • timeWindow为时间窗口的长度。

  • cut表示该资源是否已经降级

  • passCount用于记录尝试次数,当每当降级后会在接下来的时间窗口内直接失败,过了该窗口后,后尝试一定次数,passCount就是用于统计这个值。

  • pool 计划任务线程池,发生降级是,启动计划任务,在时间窗口后关闭降级开关。

下面具体分析熔断的内部实现

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Override public boolean passCheck(Context context, DefaultNode node, int acquireCount, Object... args) { if (cut.get()) {// cut是AtomicBoolean类型,默认false return false; } // 获取到该资源对应的ClusterNode 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; } if (passCount.incrementAndGet() < RT_MAX_EXCEED_N) { return true; } } else if (grade == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) { double exception = clusterNode.exceptionQps(); double success = clusterNode.successQps(); double total = clusterNode.totalQps(); // if total qps less than RT_MAX_EXCEED_N, pass. if (total < RT_MAX_EXCEED_N) { return true; } double realSuccess = success - exception; if (realSuccess <= 0 && exception < RT_MAX_EXCEED_N) { 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; }

我们知道ClusterNode保存的是一个资源的所有数据,不管它是哪个EntranceNode下的数据,都会汇总在ClusterNode中。

  • 降级策略为rt时,通过ClusterNode获取到上一秒内所有该资源请求的平均响应时间,如果小于设置的值,重置passCount,返回ture。
    如果过大于设置的值,增加尝试次数,若没超过5,则返回true,否则修改cut的值进行熔断。与此同时,启动定时任务,在timeWindow之后修改降级开关的值。

  • 如果降级策略为异常率,获取到上一秒总内请求数、异常数、成功数,若总请求小于尝试常数(5),返回true,否则计算真正成功次数,与success对应的block,即使在业务代码中跑出了异常
    success也会递增,因此realSuccess = success-exception,如果exception小于5,则通过,如果异常率小于设置的值,也通过,否则和上面一样,修改降级开关的值。并开启计划任务。

  • 如果策略为异常次数,则直接比较异常数和设定的值,如果小于则通过,否则降级。

总结:
本文对Sentinel的三种熔断降级策略从代码层面进行了分析,逻辑处理在DegradeSlot中,该slot处于ClusterBuilderSlot、StatisticSlot之后,因此所需要的success、exception等数据已经就绪。计划任务线程池作用是修改降级开关,相当于熔断自动恢复。这个任务启动之后只会执行一次(注意和fixRate的区别)并且在某一时刻最多有一个计划任务启动。

最后

以上就是超级羊最近收集整理的关于流控神器Sentinel指南:熔断降级源码分析的全部内容,更多相关流控神器Sentinel指南内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(64)

评论列表共有 0 条评论

立即
投稿
返回
顶部