聊聊sentinel的SystemSlot

本文主要研究一下sentinel的SystemSlot

SystemSlot

sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/system/SystemSlot.java

public class SystemSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

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

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

}
  • 这里是通过SystemRuleManager.checkSystem(resourceWrapper)进行系统限流判断

SystemRuleManager

    public static void checkSystem(ResourceWrapper resourceWrapper) throws BlockException {

        // 确定开关开了
        if (checkSystemStatus.get() == false) {
            return;
        }

        // for inbound traffic only
        if (resourceWrapper.getType() != EntryType.IN) {
            return;
        }

        // total qps
        double currentQps = Constants.ENTRY_NODE == null ? 0.0 : Constants.ENTRY_NODE.successQps();
        if (currentQps > qps) {
            throw new SystemBlockException(resourceWrapper.getName(), "qps");
        }

        // total thread
        int currentThread = Constants.ENTRY_NODE == null ? 0 : Constants.ENTRY_NODE.curThreadNum();
        if (currentThread > maxThread) {
            throw new SystemBlockException(resourceWrapper.getName(), "thread");
        }

        double rt = Constants.ENTRY_NODE == null ? 0 : Constants.ENTRY_NODE.avgRt();
        if (rt > maxRt) {
            throw new SystemBlockException(resourceWrapper.getName(), "rt");
        }

        // 完全按照RT,BBR算法来
        if (highestSystemLoadIsSet && getCurrentSystemAvgLoad() > highestSystemLoad) {
            if (currentThread > 1 &&
                currentThread > Constants.ENTRY_NODE.maxSuccessQps() * Constants.ENTRY_NODE.minRt() / 1000) {
                throw new SystemBlockException(resourceWrapper.getName(), "load");
            }
        }
    }

    public static double getCurrentSystemAvgLoad() {
        return statusListener.getSystemAverageLoad();
    }
  • 先判断qps,在判断总线程数、之后判断rt,最后判断系统负载有没有超过限制

StatisticNode

sentinel-core/src/main/java/com/alibaba/csp/sentinel/node/StatisticNode.java

    @Override
    public long successQps() {
        return rollingCounterInSecond.success() / IntervalProperty.INTERVAL;
    }

    @Override
    public int curThreadNum() {
        return curThreadNum.get();
    }

    @Override
    public long avgRt() {
        long successCount = rollingCounterInSecond.success();
        if (successCount == 0) {
            return 0;
        }

        return rollingCounterInSecond.rt() / successCount;
    }

    @Override
    public long maxSuccessQps() {
        return rollingCounterInSecond.maxSuccess() * SampleCountProperty.sampleCount;
    }

    @Override
    public long minRt() {
        return rollingCounterInSecond.minRt();
    }
  • successQps、curThreadNum、avgRt、maxSuccessQps、minRt指标在StatisticNode上进行维护

SystemStatusListener

sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/system/SystemStatusListener.java

public class SystemStatusListener implements Runnable {

    volatile double currentLoad = -1;

    volatile String reason = StringUtil.EMPTY;

    static final int processor = ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors();

    public double getSystemAverageLoad() {
        return currentLoad;
    }

    @Override
    public void run() {
        try {
            if (!SystemRuleManager.getCheckSystemStatus()) {
                return;
            }

            // system average load
            OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
            currentLoad = operatingSystemMXBean.getSystemLoadAverage();

            StringBuilder sb = new StringBuilder();
            if (currentLoad > SystemRuleManager.getHighestSystemLoad()) {
                sb.append("load:").append(currentLoad).append(";");
                sb.append("qps:").append(Constants.ENTRY_NODE.passQps()).append(";");
                sb.append("rt:").append(Constants.ENTRY_NODE.avgRt()).append(";");
                sb.append("thread:").append(Constants.ENTRY_NODE.curThreadNum()).append(";");
                sb.append("success:").append(Constants.ENTRY_NODE.successQps()).append(";");
                sb.append("minRt:").append(Constants.ENTRY_NODE.minRt()).append(";");
                sb.append("maxSuccess:").append(Constants.ENTRY_NODE.maxSuccessQps()).append(";");
                RecordLog.info(sb.toString());
            }

        } catch (Throwable e) {
            RecordLog.info("could not get system error ", e);
        }
    }

}
  • 系统负载是通过SystemRuleManager定时调度SystemStatusListener,通过OperatingSystemMXBean去获取
    static {
        checkSystemStatus.set(false);
        statusListener = new SystemStatusListener();
        scheduler.scheduleAtFixedRate(statusListener, 5, 1, TimeUnit.SECONDS);
        currentProperty.addListener(listener);
    }

小结

sentinel的SystemSlot是通过判断系统相关指标来进行限流,主要的指标为qps、总线程数、rt、系统负载。

doc

  • SystemSlot

原文发布于微信公众号 - 码匠的流水账(geek_luandun)

原文发表时间:2018-09-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术小黑屋

避免Android中Context引起的内存泄露

Context是我们在编写Android程序经常使用到的对象,意思为上下文对象。 常用的有Activity的Context还是有Application的Cont...

901
来自专栏Android 开发学习

Android Architecture Components 之LiveData, ViewModel

3034
来自专栏开发之途

Android 解析RecyclerView(1)——带点击事件监听的通用Adapter

1703
来自专栏Android开发指南

2.抽取代码(BaseActivity)

3588
来自专栏Android Note

Android - 接口、MVP 的使用心得

想象一下,有这么一个场景(需求),两个不同的页面,但是页面的展示 UI 是完全相同的。这时候你会想到,这很简单啊,复用吗。但但但但是,它们的数据格式是完全不相同...

992
来自专栏码匠的流水账

聊聊spring cloud gateway的RedirectToGatewayFilter

本文主要研究下spring cloud gateway的RedirectToGatewayFilter

1691
来自专栏水击三千

Android应用开发SharedPreferences存储数据的使用方法

SharedPreferences是Android中最容易理解的数据存储技术,实际上SharedPreferences处理的就是一个key-value(键值对)...

3236
来自专栏分享达人秀

完善RecyclerView,添加首尾视图

在之前学习ListView的时候,有学习过如何给ListView添加列表头和列表尾。但是通过近几期的学习,发现RecyclerView是一个比ListV...

2438
来自专栏向治洪

仿淘宝收货地址,本地数据库

谁说咱们攻城狮不能写出既幽默又能懂的博客呢,本人想推出一系列博文,可以给刚接触Android开发的做一个参考,也可以与接触Android已久的各路大神比较一下,...

1.3K7
来自专栏everhad

[异常特工]android常见bug跟踪

前言 对app的线上bug的收集(友盟、云捕等)有时会得到这样的异常堆栈信息:没有一行代码是有关自身程序代码的。这使得对bug的解决无从下手,根据经验,内存不足...

2085

扫码关注云+社区

领取腾讯云代金券