概述

DegradeSlot 位于 FlowSlot 后一个节点,负责降级处理,是降级的核心。

解析

与限流类似,降级是委托给Manager去处理的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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);
}

@Override
public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
fireExit(context, resourceWrapper, count, args);
}
}

DegradeRuleManager

  1. 根据资源名称获取所有的降级规则;
  2. 执行对应的降级规则的passCheck方法;
  3. 如果没有通过则抛出DegradeException。
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 {

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

成员变量

1
2
3
4
5
6
7
8
// rt上限或者异常比例异常数
private double count;
// 降级持续的时间窗口
private int timeWindow;
// 降级策略:0平均rt,1异常率
private int grade = RuleConstant.DEGRADE_GRADE_RT;
private final AtomicBoolean cut = new AtomicBoolean(false);
private AtomicLong passCount = new AtomicLong(0);

passCheck 限流校验

返回true代表本次请求不降级,返回false则代表降级。

  1. 判断标志位cut是否已经进入降级状态,是则直接返回false,不然继续;
  2. 平均响应时间策略:
    1. 当前平均响应时间小于设置值则返回true;
    2. 超过平均rt的前RT_MAX_EXCEED_N(5)次请求返回true;
  3. 异常比例策略:
    1. RT_MAX_EXCEED_N(5)次请求内直接返回true;
    2. 如果成功数小于异常数,且异常数小于RT_MAX_EXCEED_N(5)次,则直接返回true;
    3. 异常比例小于设定值,返回true;
  4. 异常数策略:
    1. 异常数小于设定值,则返回true;
  5. 将标志位cut设置为true;
    1. 设置延时任务,延时timeWindow秒后将标志位设置为false;
  6. 返回false;
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
@Override
public boolean passCheck(Context context, DefaultNode node, int acquireCount, Object... args) {
if (cut.get()) {// 已经进入降级了,直接返回false
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;
}

// Sentinel will degrade the service only if count exceeds.
// 超过平均rt的前RT_MAX_EXCEED_N(5)次请求可以通过
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.
// 只有超过RT_MAX_EXCEED_N(5)次请求才会生效
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;
}
}
// 走的这里说明进入降级了,将标志位cut设置为true
if (cut.compareAndSet(false, true)) {
// 定时任务,在timeWindow秒后将cut设置为false
ResetTask resetTask = new ResetTask(this);
pool.schedule(resetTask, timeWindow, TimeUnit.SECONDS);
}

return false;
}

private static final class ResetTask implements Runnable {
private DegradeRule rule;

ResetTask(DegradeRule rule) {
this.rule = rule;
}
@Override
public void run() {
rule.getPassCount().set(0);
rule.cut.set(false);
}
}