当前位置: 首页 > news >正文

聊聊sentinel的DegradeSlot

本文主要研究一下sentinel的DegradeSlot

DegradeSlot

com/alibaba/csp/sentinel/slots/block/degrade/DegradeSlot.java

public class DegradeSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, Object... args)
        throws Throwable {
        DegradeRuleManager.checkDegrade(resourceWrapper, context, node, count);
        fireEntry(context, resourceWrapper, node, count, args);
    }

    @Override
    public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
        fireExit(context, resourceWrapper, count, args);
    }
}
  • 调用DegradeRuleManager.checkDegrade进行降级规则检测

DegradeRuleManager

com/alibaba/csp/sentinel/slots/block/degrade/DegradeRuleManager.java

public class DegradeRuleManager {

    private static volatile Map<String, List<DegradeRule>> degradeRules
        = new ConcurrentHashMap<String, List<DegradeRule>>();

    final static RulePropertyListener listener = new RulePropertyListener();
    private static SentinelProperty<List<DegradeRule>> currentProperty
        = new DynamicSentinelProperty<List<DegradeRule>>();

    static {
        currentProperty.addListener(listener);
    }

    /**
     * Listen to the {@link SentinelProperty} for {@link DegradeRule}s. The property is the source
     * of {@link DegradeRule}s. Degrade rules can also be set by {@link #loadRules(List)} directly.
     *
     * @param property the property to listen.
     */
    public static void register2Property(SentinelProperty<List<DegradeRule>> property) {
        synchronized (listener) {
            currentProperty.removeListener(listener);
            property.addListener(listener);
            currentProperty = property;
        }
    }

    public static void checkDegrade(ResourceWrapper resource, Context context, DefaultNode node, int count)
        throws BlockException {
        if (degradeRules == null) {
            return;
        }

        List<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());
            }
        }
    }

    //......
}
  • checkDegrade根据资源名称获取对应的降级规则,然后挨个遍历检查

DegradeRule

com/alibaba/csp/sentinel/slots/block/degrade/DegradeRule.java

/**
 * <p>
 * Degrade is used when the resources are in an unstable state, these resources
 * will be degraded within the next defined time window. There are two ways to
 * measure whether a resource is stable or not:
 * </p>
 * <ul>
 * <li>
 * Average response time ({@code DEGRADE_GRADE_RT}): When
 * the average RT exceeds the threshold ('count' in 'DegradeRule', in milliseconds), the
 * resource enters a quasi-degraded state. If the RT of next coming 5
 * requests still exceed this threshold, this resource will be downgraded, which
 * means that in the next time window (defined in 'timeWindow', in seconds) all the
 * access to this resource will be blocked.
 * </li>
 * <li>
 * Exception ratio: When the ratio of exception count per second and the
 * success qps exceeds the threshold, access to the resource will be blocked in
 * the coming window.
 * </li>
 * </ul>
 *
 * @author jialiang.linjl
 */
public class DegradeRule extends AbstractRule {

    private static final int RT_MAX_EXCEED_N = 5;

    private static ScheduledExecutorService pool = Executors.newScheduledThreadPool(
        Runtime.getRuntime().availableProcessors(), new NamedThreadFactory("sentinel-degrade-reset-task", true));

    /**
     * RT threshold or exception ratio threshold count.
     */
    private double count;

    /**
     * Degrade recover timeout (in seconds) when degradation occurs.
     */
    private int timeWindow;

    /**
     * Degrade strategy (0: average RT, 1: exception ratio).
     */
    private int grade = RuleConstant.DEGRADE_GRADE_RT;

    private volatile boolean cut = false;

    public int getGrade() {
        return grade;
    }

    public void setGrade(int grade) {
        this.grade = grade;
    }

    private AtomicLong passCount = new AtomicLong(0);

    private final Object lock = new Object();

    //......

    @Override
    public boolean passCheck(Context context, DefaultNode node, int acquireCount, Object... args) {

        if (cut) {
            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.
            if (passCount.incrementAndGet() < RT_MAX_EXCEED_N) {
                return true;
            }
        } else {
            double exception = clusterNode.exceptionQps();
            double success = clusterNode.successQps();
            long total = clusterNode.totalQps();
            // if total qps less than RT_MAX_EXCEED_N, pass.
            if (total < RT_MAX_EXCEED_N) {
                return true;
            }

            if (success == 0) {
                return exception < RT_MAX_EXCEED_N;
            }

            if (exception / (success + exception) < count) {
                return true;
            }
        }

        synchronized (lock) {
            if (!cut) {
                // Automatically degrade.
                cut = 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.setCut(false);
        }
    }
}
  • 这个passCheck根据平均响应时间以及异常个数等进行降级判断
  • 触发降级时标志cut为true,然后启动一个ResetTask,在指定时间窗口之后重置cut为false并清空passCount计数

小结

sentinel的DegradeSlot主要依据平均响应时间以及异常次数来判断,进入降级模式时启动定时任务在指定时间窗口重置相关计数,恢复到正常模式。

doc

  • DegradeSlot

相关文章:

  • 前端UI框架选择区别对比推荐
  • 解压缩软件居然还有多种工作模式!长见识了
  • 小白科普:分布式和集群
  • dubbo与springcloud初识
  • Android 5.1 预制输入法
  • Python游戏《外星人入侵》来了~
  • win10装双系统图文教程
  • 第10章神经网络基础
  • MpVue 致力打造H5与小程序的代码共用
  • 参加2018之江杯全球人工智能大赛 :视频识别问答(三)
  • 解决加载模型预测数据时报错的问题
  • java 颠倒整数
  • 【火炉炼AI】机器学习022-使用均值漂移聚类算法构建模型
  • Python从菜鸟到高手(5):数字
  • python中的None
  • @jsonView过滤属性
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • MySQL数据库运维之数据恢复
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • python大佬养成计划----difflib模块
  • Python进阶细节
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 百度小程序遇到的问题
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 翻译:Hystrix - How To Use
  • 聊聊flink的BlobWriter
  • 浅谈web中前端模板引擎的使用
  • 我从编程教室毕业
  • 应用生命周期终极 DevOps 工具包
  • 阿里云重庆大学大数据训练营落地分享
  • 翻译 | The Principles of OOD 面向对象设计原则
  • #pragam once 和 #ifndef 预编译头
  • $(selector).each()和$.each()的区别
  • $.ajax()参数及用法
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (3)选择元素——(17)练习(Exercises)
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (四)linux文件内容查看
  • .NET : 在VS2008中计算代码度量值
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • @for /l %i in (1,1,10) do md %i 批处理自动建立目录
  • @reference注解_Dubbo配置参考手册之dubbo:reference
  • [ C++ ] STL---仿函数与priority_queue
  • [04] Android逐帧动画(一)
  • [AIGC 大数据基础]hive浅谈
  • [Android] 修改设备访问权限
  • [C++]类和对象【上篇】
  • [CTO札记]如何测试用户接受度?
  • [ffmpeg] 定制滤波器