聊聊sentinel的SystemSlot

本文主要研究一下sentinel的SystemSlotjava

SystemSlot

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

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.javagit

@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.javagithub

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

相關文章
相關標籤/搜索