Signed-off-by: Carpenter Lee <hooleeucas@163.com>master
@@ -34,6 +34,7 @@ import com.alibaba.csp.sentinel.slots.block.AbstractRule; | |||||
* </p> | * </p> | ||||
* | * | ||||
* @author jialiang.linjl | * @author jialiang.linjl | ||||
* @author Carpenter Lee | |||||
* @see SystemRuleManager | * @see SystemRuleManager | ||||
*/ | */ | ||||
public class SystemRule extends AbstractRule { | public class SystemRule extends AbstractRule { | ||||
@@ -42,6 +43,10 @@ public class SystemRule extends AbstractRule { | |||||
* negative value means no threshold checking. | * negative value means no threshold checking. | ||||
*/ | */ | ||||
private double highestSystemLoad = -1; | private double highestSystemLoad = -1; | ||||
/** | |||||
* cpu usage, between [0, 1] | |||||
*/ | |||||
private double highestCpuUsage = -1; | |||||
private double qps = -1; | private double qps = -1; | ||||
private long avgRt = -1; | private long avgRt = -1; | ||||
private long maxThread = -1; | private long maxThread = -1; | ||||
@@ -110,6 +115,24 @@ public class SystemRule extends AbstractRule { | |||||
this.highestSystemLoad = highestSystemLoad; | this.highestSystemLoad = highestSystemLoad; | ||||
} | } | ||||
/** | |||||
* Get highest cpu usage. Cpu usage is between [0, 1] | |||||
* | |||||
* @return highest cpu usage | |||||
*/ | |||||
public double getHighestCpuUsage() { | |||||
return highestCpuUsage; | |||||
} | |||||
/** | |||||
* set highest cpu usage. Cpu usage is between [0, 1] | |||||
* | |||||
* @param highestCpuUsage the value to set. | |||||
*/ | |||||
public void setHighestCpuUsage(double highestCpuUsage) { | |||||
this.highestCpuUsage = highestCpuUsage; | |||||
} | |||||
@Override | @Override | ||||
public boolean passCheck(Context context, DefaultNode node, int count, Object... args) { | public boolean passCheck(Context context, DefaultNode node, int count, Object... args) { | ||||
return true; | return true; | ||||
@@ -132,6 +155,9 @@ public class SystemRule extends AbstractRule { | |||||
if (Double.compare(that.highestSystemLoad, highestSystemLoad) != 0) { | if (Double.compare(that.highestSystemLoad, highestSystemLoad) != 0) { | ||||
return false; | return false; | ||||
} | } | ||||
if (Double.compare(that.highestCpuUsage, highestCpuUsage) != 0) { | |||||
return false; | |||||
} | |||||
if (Double.compare(that.qps, qps) != 0) { | if (Double.compare(that.qps, qps) != 0) { | ||||
return false; | return false; | ||||
@@ -150,6 +176,9 @@ public class SystemRule extends AbstractRule { | |||||
temp = Double.doubleToLongBits(highestSystemLoad); | temp = Double.doubleToLongBits(highestSystemLoad); | ||||
result = 31 * result + (int)(temp ^ (temp >>> 32)); | result = 31 * result + (int)(temp ^ (temp >>> 32)); | ||||
temp = Double.doubleToLongBits(highestCpuUsage); | |||||
result = 31 * result + (int)(temp ^ (temp >>> 32)); | |||||
temp = Double.doubleToLongBits(qps); | temp = Double.doubleToLongBits(qps); | ||||
result = 31 * result + (int)(temp ^ (temp >>> 32)); | result = 31 * result + (int)(temp ^ (temp >>> 32)); | ||||
@@ -162,6 +191,7 @@ public class SystemRule extends AbstractRule { | |||||
public String toString() { | public String toString() { | ||||
return "SystemRule{" + | return "SystemRule{" + | ||||
"highestSystemLoad=" + highestSystemLoad + | "highestSystemLoad=" + highestSystemLoad + | ||||
", highestCpuUsage=" + highestCpuUsage + | |||||
", qps=" + qps + | ", qps=" + qps + | ||||
", avgRt=" + avgRt + | ", avgRt=" + avgRt + | ||||
", maxThread=" + maxThread + | ", maxThread=" + maxThread + | ||||
@@ -66,6 +66,10 @@ import com.alibaba.csp.sentinel.slots.block.BlockException; | |||||
public class SystemRuleManager { | public class SystemRuleManager { | ||||
private static volatile double highestSystemLoad = Double.MAX_VALUE; | private static volatile double highestSystemLoad = Double.MAX_VALUE; | ||||
/** | |||||
* cpu usage, between [0, 1] | |||||
*/ | |||||
private static volatile double highestCpuUsage = Double.MAX_VALUE; | |||||
private static volatile double qps = Double.MAX_VALUE; | private static volatile double qps = Double.MAX_VALUE; | ||||
private static volatile long maxRt = Long.MAX_VALUE; | private static volatile long maxRt = Long.MAX_VALUE; | ||||
private static volatile long maxThread = Long.MAX_VALUE; | private static volatile long maxThread = Long.MAX_VALUE; | ||||
@@ -73,6 +77,7 @@ public class SystemRuleManager { | |||||
* mark whether the threshold are set by user. | * mark whether the threshold are set by user. | ||||
*/ | */ | ||||
private static volatile boolean highestSystemLoadIsSet = false; | private static volatile boolean highestSystemLoadIsSet = false; | ||||
private static volatile boolean highestCpuUsageIsSet = false; | |||||
private static volatile boolean qpsIsSet = false; | private static volatile boolean qpsIsSet = false; | ||||
private static volatile boolean maxRtIsSet = false; | private static volatile boolean maxRtIsSet = false; | ||||
private static volatile boolean maxThreadIsSet = false; | private static volatile boolean maxThreadIsSet = false; | ||||
@@ -134,6 +139,12 @@ public class SystemRuleManager { | |||||
result.add(loadRule); | result.add(loadRule); | ||||
} | } | ||||
if (highestCpuUsageIsSet) { | |||||
SystemRule rule = new SystemRule(); | |||||
rule.setHighestCpuUsage(highestCpuUsage); | |||||
result.add(rule); | |||||
} | |||||
if (maxRtIsSet) { | if (maxRtIsSet) { | ||||
SystemRule rtRule = new SystemRule(); | SystemRule rtRule = new SystemRule(); | ||||
rtRule.setAvgRt(maxRt); | rtRule.setAvgRt(maxRt); | ||||
@@ -185,9 +196,18 @@ public class SystemRuleManager { | |||||
checkSystemStatus.set(false); | checkSystemStatus.set(false); | ||||
} | } | ||||
RecordLog.info(String.format("[SystemRuleManager] Current system check status: %s, highestSystemLoad: " | |||||
+ highestSystemLoad + ", " + "maxRt: %d, maxThread: %d, maxQps: " + qps, checkSystemStatus.get(), maxRt, maxThread)); | |||||
RecordLog.info(String.format("[SystemRuleManager] Current system check status: %s, " | |||||
+ "highestSystemLoad: %e, " | |||||
+ "highestCpuUsage: %e, " | |||||
+ "maxRt: %d, " | |||||
+ "maxThread: %d, " | |||||
+ "maxQps: %e", | |||||
checkSystemStatus.get(), | |||||
highestSystemLoad, | |||||
highestCpuUsage, | |||||
maxRt, | |||||
maxThread, | |||||
qps)); | |||||
} | } | ||||
protected void restoreSetting() { | protected void restoreSetting() { | ||||
@@ -195,6 +215,7 @@ public class SystemRuleManager { | |||||
// should restore changes | // should restore changes | ||||
highestSystemLoad = Double.MAX_VALUE; | highestSystemLoad = Double.MAX_VALUE; | ||||
highestCpuUsage = Double.MAX_VALUE; | |||||
maxRt = Long.MAX_VALUE; | maxRt = Long.MAX_VALUE; | ||||
maxThread = Long.MAX_VALUE; | maxThread = Long.MAX_VALUE; | ||||
qps = Double.MAX_VALUE; | qps = Double.MAX_VALUE; | ||||
@@ -229,6 +250,12 @@ public class SystemRuleManager { | |||||
checkStatus = true; | checkStatus = true; | ||||
} | } | ||||
if (rule.getHighestCpuUsage() >= 0) { | |||||
highestCpuUsage = Math.min(highestCpuUsage, rule.getHighestCpuUsage()); | |||||
highestCpuUsageIsSet = true; | |||||
checkStatus = true; | |||||
} | |||||
if (rule.getAvgRt() >= 0) { | if (rule.getAvgRt() >= 0) { | ||||
maxRt = Math.min(maxRt, rule.getAvgRt()); | maxRt = Math.min(maxRt, rule.getAvgRt()); | ||||
maxRtIsSet = true; | maxRtIsSet = true; | ||||
@@ -284,17 +311,34 @@ public class SystemRuleManager { | |||||
throw new SystemBlockException(resourceWrapper.getName(), "rt"); | throw new SystemBlockException(resourceWrapper.getName(), "rt"); | ||||
} | } | ||||
// BBR algorithm. | |||||
// load. BBR algorithm. | |||||
if (highestSystemLoadIsSet && getCurrentSystemAvgLoad() > highestSystemLoad) { | if (highestSystemLoadIsSet && getCurrentSystemAvgLoad() > highestSystemLoad) { | ||||
if (currentThread > 1 && | |||||
currentThread > Constants.ENTRY_NODE.maxSuccessQps() * Constants.ENTRY_NODE.minRt() / 1000) { | |||||
if (!checkBbr(currentThread)) { | |||||
throw new SystemBlockException(resourceWrapper.getName(), "load"); | throw new SystemBlockException(resourceWrapper.getName(), "load"); | ||||
} | } | ||||
} | } | ||||
// cpu usage | |||||
if (highestCpuUsageIsSet && getCurrentCpuUsage() > highestCpuUsage) { | |||||
if (!checkBbr(currentThread)) { | |||||
throw new SystemBlockException(resourceWrapper.getName(), "cpu"); | |||||
} | |||||
} | |||||
} | |||||
private static boolean checkBbr(int currentThread) { | |||||
if (currentThread > 1 && | |||||
currentThread > Constants.ENTRY_NODE.maxSuccessQps() * Constants.ENTRY_NODE.minRt() / 1000) { | |||||
return false; | |||||
} | |||||
return true; | |||||
} | } | ||||
public static double getCurrentSystemAvgLoad() { | public static double getCurrentSystemAvgLoad() { | ||||
return statusListener.getSystemAverageLoad(); | return statusListener.getSystemAverageLoad(); | ||||
} | } | ||||
public static double getCurrentCpuUsage() { | |||||
return statusListener.getCpuUsage(); | |||||
} | |||||
} | } |
@@ -16,11 +16,12 @@ | |||||
package com.alibaba.csp.sentinel.slots.system; | package com.alibaba.csp.sentinel.slots.system; | ||||
import java.lang.management.ManagementFactory; | import java.lang.management.ManagementFactory; | ||||
import java.lang.management.OperatingSystemMXBean; | |||||
import com.alibaba.csp.sentinel.Constants; | |||||
import com.alibaba.csp.sentinel.log.RecordLog; | import com.alibaba.csp.sentinel.log.RecordLog; | ||||
import com.alibaba.csp.sentinel.util.StringUtil; | import com.alibaba.csp.sentinel.util.StringUtil; | ||||
import com.alibaba.csp.sentinel.Constants; | |||||
import com.sun.management.OperatingSystemMXBean; | |||||
/** | /** | ||||
* @author jialiang.linjl | * @author jialiang.linjl | ||||
@@ -28,6 +29,7 @@ import com.alibaba.csp.sentinel.Constants; | |||||
public class SystemStatusListener implements Runnable { | public class SystemStatusListener implements Runnable { | ||||
volatile double currentLoad = -1; | volatile double currentLoad = -1; | ||||
volatile double currentCpuUsage = -1; | |||||
volatile String reason = StringUtil.EMPTY; | volatile String reason = StringUtil.EMPTY; | ||||
@@ -37,6 +39,10 @@ public class SystemStatusListener implements Runnable { | |||||
return currentLoad; | return currentLoad; | ||||
} | } | ||||
public double getCpuUsage() { | |||||
return currentCpuUsage; | |||||
} | |||||
@Override | @Override | ||||
public void run() { | public void run() { | ||||
try { | try { | ||||
@@ -44,13 +50,22 @@ public class SystemStatusListener implements Runnable { | |||||
return; | return; | ||||
} | } | ||||
// system average load | |||||
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean(); | |||||
currentLoad = operatingSystemMXBean.getSystemLoadAverage(); | |||||
OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class); | |||||
currentLoad = osBean.getSystemLoadAverage(); | |||||
/** | |||||
* Java Doc copied from {@link OperatingSystemMXBean#getSystemCpuLoad()}:</br> | |||||
* Returns the "recent cpu usage" for the whole system. This value is a double in the [0.0,1.0] interval. | |||||
* A value of 0.0 means that all CPUs were idle during the recent period of time observed, while a value | |||||
* of 1.0 means that all CPUs were actively running 100% of the time during the recent period being | |||||
* observed. All values betweens 0.0 and 1.0 are possible depending of the activities going on in the | |||||
* system. If the system recent cpu usage is not available, the method returns a negative value. | |||||
*/ | |||||
currentCpuUsage = osBean.getSystemCpuLoad(); | |||||
StringBuilder sb = new StringBuilder(); | StringBuilder sb = new StringBuilder(); | ||||
if (currentLoad > SystemRuleManager.getHighestSystemLoad()) { | if (currentLoad > SystemRuleManager.getHighestSystemLoad()) { | ||||
sb.append("load:").append(currentLoad).append(";"); | sb.append("load:").append(currentLoad).append(";"); | ||||
sb.append("cpu:").append(currentCpuUsage).append(";"); | |||||
sb.append("qps:").append(Constants.ENTRY_NODE.passQps()).append(";"); | sb.append("qps:").append(Constants.ENTRY_NODE.passQps()).append(";"); | ||||
sb.append("rt:").append(Constants.ENTRY_NODE.avgRt()).append(";"); | sb.append("rt:").append(Constants.ENTRY_NODE.avgRt()).append(";"); | ||||
sb.append("thread:").append(Constants.ENTRY_NODE.curThreadNum()).append(";"); | sb.append("thread:").append(Constants.ENTRY_NODE.curThreadNum()).append(";"); | ||||
@@ -91,6 +91,8 @@ public class SystemGuardDemo { | |||||
SystemRule rule = new SystemRule(); | SystemRule rule = new SystemRule(); | ||||
// max load is 3 | // max load is 3 | ||||
rule.setHighestSystemLoad(3.0); | rule.setHighestSystemLoad(3.0); | ||||
// max cpu usage is 60% | |||||
rule.setHighestCpuUsage(0.6); | |||||
// max avg rt of all request is 10 ms | // max avg rt of all request is 10 ms | ||||
rule.setAvgRt(10); | rule.setAvgRt(10); | ||||
// max total qps is 20 | // max total qps is 20 | ||||