概述
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
- 根据资源名称获取所有的降级规则;
- 执行对应的降级规则的passCheck方法;
- 如果没有通过则抛出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
| private double count;
private int timeWindow;
private int grade = RuleConstant.DEGRADE_GRADE_RT; private final AtomicBoolean cut = new AtomicBoolean(false); private AtomicLong passCount = new AtomicLong(0);
|
passCheck 限流校验
返回true代表本次请求不降级,返回false则代表降级。
- 判断标志位cut是否已经进入降级状态,是则直接返回false,不然继续;
- 平均响应时间策略:
- 当前平均响应时间小于设置值则返回true;
- 超过平均rt的前RT_MAX_EXCEED_N(5)次请求返回true;
- 异常比例策略:
- RT_MAX_EXCEED_N(5)次请求内直接返回true;
- 如果成功数小于异常数,且异常数小于RT_MAX_EXCEED_N(5)次,则直接返回true;
- 异常比例小于设定值,返回true;
- 异常数策略:
- 异常数小于设定值,则返回true;
- 将标志位cut设置为true;
- 设置延时任务,延时timeWindow秒后将标志位设置为false;
- 返回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()) { 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; }
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 < 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; }
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); } }
|