序
本文主要研究一下sentinel的SystemSlot
SystemSlot
sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/system/SystemSlot.java
public class SystemSlot extends AbstractLinkedProcessorSlot{ @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、系统负载。