Анализ принципа деградации Sentinel Fuse

Java

В предыдущей статье был представлен основной принцип работы и текущий ограничивающий принцип дозорного. В этой статье будет проанализирован принцип понижения версии Fuse с точки зрения исходного кода. Операция предохранителя расположена в конце цепочки обработки слотов и обрабатывается классом с именем DegradeSlot, давайте взглянем на его исходный код.

@SpiOrder(-1000)
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 и введите метод checkDegrade DegradeRuleManager.

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) {
        	//如果达到了熔断条件,就会抛出DegradeException的异常
            if (!rule.passCheck(context, node, count)) {
                throw new DegradeException(rule.getLimitApp(), rule);
            }
        }
    }

Решение предохранителя заключается в том, чтобы судить и обрабатывать правила, установленные для ресурсов, один за другим. Если одно из условий не выполняется, выбрасывается исключение DegradeException. Итак, как принимается решение о предохранителе? Продолжайте углубляться в метод passCheck в классе DegradeRule.Прежде чем анализировать метод passCheck, мы представим несколько важных полей класса DegradeRule.

	//慢请求或异常请求的计数
    private double count;

	//熔断窗口
    private int timeWindow;
    
    //熔断策略 (0: 慢调用, 1: 异常率, 2: 异常数) 
    private int grade = RuleConstant.DEGRADE_GRADE_RT;

    /**
     * 针对慢调用,如果慢调用数小于其值(默认为5),是不会触发熔断的
     *
     * @since 1.7.0
     */
    private int rtSlowRequestAmount = RuleConstant.DEGRADE_DEFAULT_SLOW_REQUEST_AMOUNT;

    /**
     * 针对异常率,如果异常数小于其值(默认为5),是不会触发熔断的
     *
     * @since 1.7.0
     */
    private int minRequestAmount = RuleConstant.DEGRADE_DEFAULT_MIN_REQUEST_AMOUNT;

Принцип реализации слияния заключается в том, чтобы просто оценить, превышает ли соответствующая статистика подсчета пороговое значение в соответствии с конкретной стратегией слияния, установленной в течение заданного времени окна, и если оно превышает, механизм слияния будет запущен. Погрузитесь в исходный код passCheck

 //慢调用计数
 private AtomicLong passCount = new AtomicLong(0);
 //熔断降级标记位,如果为true,则表示触发了熔断
 private final AtomicBoolean cut = new AtomicBoolean(false);
 
 public boolean passCheck(Context context, DefaultNode node, int acquireCount, Object... args) {
 		//如果标记位为真,表示已触发熔断
        if (cut.get()) {
            return false;
        }
		//获取资源计数统计node
        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;
            }

            //如果慢调用数小于默认的最小门限数(5),则不进行熔断降级
            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();
    		//如果总调用数小于默认的门限值(5),则不会触发熔断降级	
            if (total < minRequestAmount) {
                return true;
            }
			//此句需要好好理解下,它表达的意思是:在异常数小于最小门限的条件是不进行熔断降级的,但前提是所用调用都不能全是异常调用
            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;
            }
        }
        //如果走到了这里,则表示将要触发熔断降级了
		//重置慢调用统计时间窗口,此处用了CAS的方法来设置标志位,防止并发。时间窗口的重置是依赖于定时任务来完成的,当timeWindow时间后,会重置熔断标志位和计数统计
        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.passCount.set(0);
            //熔断标志位
            rule.cut.set(false);
        }
    }

Приведенный выше код описывает основной процесс слияния и понижения версии.Для приведенного выше кода следует отметить, что:

  • Медленные вызовы осуществляются черезвременное окноЧтобы подсчитать количество медленных вызовов для достижения
  • Исключительная норма дляв секундуСоотношение количества исключений и количества успехов для определения выполнения условий срабатывания
  • Количество исключений длякаждую минутуКоличество аномальной статистики для достижения

При срабатывании автоматического выключателя бит флага будет установлен в значение true и будет длиться в течение длительного времени Window, которое задается разработчиком при настройке правила понижения уровня автоматического выключателя. Выше приведен процесс реализации полного понижения версии предохранителя.С точки зрения кода, окно предохранителя обновляется с помощью временной задачи, и дизайн является относительно новым.