Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Add CPU usage checking support in system protection rule #484

Merged
merged 2 commits into from
Mar 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@

<!-- Build -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.source.version>1.6</java.source.version>
<java.target.version>1.6</java.target.version>
<java.source.version>1.7</java.source.version>
<java.target.version>1.7</java.target.version>
<java.encoding>UTF-8</java.encoding>
<maven.compiler.version>3.8.0</maven.compiler.version>
<maven.surefire.version>2.22.1</maven.surefire.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
* </p>
*
* @author jialiang.linjl
* @author Carpenter Lee
* @see SystemRuleManager
*/
public class SystemRule extends AbstractRule {
Expand All @@ -42,6 +43,10 @@ public class SystemRule extends AbstractRule {
* negative value means no threshold checking.
*/
private double highestSystemLoad = -1;
/**
* cpu usage, between [0, 1]
*/
private double highestCpuUsage = -1;
private double qps = -1;
private long avgRt = -1;
private long maxThread = -1;
Expand Down Expand Up @@ -110,6 +115,24 @@ public void setHighestSystemLoad(double 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
public boolean passCheck(Context context, DefaultNode node, int count, Object... args) {
return true;
Expand All @@ -132,6 +155,9 @@ public boolean equals(Object o) {
if (Double.compare(that.highestSystemLoad, highestSystemLoad) != 0) {
return false;
}
if (Double.compare(that.highestCpuUsage, highestCpuUsage) != 0) {
return false;
}

if (Double.compare(that.qps, qps) != 0) {
return false;
Expand All @@ -150,6 +176,9 @@ public int hashCode() {
temp = Double.doubleToLongBits(highestSystemLoad);
result = 31 * result + (int)(temp ^ (temp >>> 32));

temp = Double.doubleToLongBits(highestCpuUsage);
result = 31 * result + (int)(temp ^ (temp >>> 32));

temp = Double.doubleToLongBits(qps);
result = 31 * result + (int)(temp ^ (temp >>> 32));

Expand All @@ -162,6 +191,7 @@ public int hashCode() {
public String toString() {
return "SystemRule{" +
"highestSystemLoad=" + highestSystemLoad +
", highestCpuUsage=" + highestCpuUsage +
", qps=" + qps +
", avgRt=" + avgRt +
", maxThread=" + maxThread +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,18 @@
public class SystemRuleManager {

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 long maxRt = Long.MAX_VALUE;
private static volatile long maxThread = Long.MAX_VALUE;
/**
* mark whether the threshold are set by user.
*/
private static volatile boolean highestSystemLoadIsSet = false;
private static volatile boolean highestCpuUsageIsSet = false;
private static volatile boolean qpsIsSet = false;
private static volatile boolean maxRtIsSet = false;
private static volatile boolean maxThreadIsSet = false;
Expand Down Expand Up @@ -134,6 +139,12 @@ public static List<SystemRule> getRules() {
result.add(loadRule);
}

if (highestCpuUsageIsSet) {
SystemRule rule = new SystemRule();
rule.setHighestCpuUsage(highestCpuUsage);
result.add(rule);
}

if (maxRtIsSet) {
SystemRule rtRule = new SystemRule();
rtRule.setAvgRt(maxRt);
Expand Down Expand Up @@ -185,16 +196,26 @@ public void configUpdate(List<SystemRule> rules) {
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() {
checkSystemStatus.set(false);

// should restore changes
highestSystemLoad = Double.MAX_VALUE;
highestCpuUsage = Double.MAX_VALUE;
maxRt = Long.MAX_VALUE;
maxThread = Long.MAX_VALUE;
qps = Double.MAX_VALUE;
Expand Down Expand Up @@ -229,6 +250,12 @@ public static void loadSystemConf(SystemRule rule) {
checkStatus = true;
}

if (rule.getHighestCpuUsage() >= 0) {
highestCpuUsage = Math.min(highestCpuUsage, rule.getHighestCpuUsage());
highestCpuUsageIsSet = true;
checkStatus = true;
}

if (rule.getAvgRt() >= 0) {
maxRt = Math.min(maxRt, rule.getAvgRt());
maxRtIsSet = true;
Expand Down Expand Up @@ -284,17 +311,34 @@ public static void checkSystem(ResourceWrapper resourceWrapper) throws BlockExce
throw new SystemBlockException(resourceWrapper.getName(), "rt");
}

// BBR algorithm.
// load. BBR algorithm.
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");
}
}

// 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() {
return statusListener.getSystemAverageLoad();
}

public static double getCurrentCpuUsage() {
return statusListener.getCpuUsage();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@
package com.alibaba.csp.sentinel.slots.system;

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.util.StringUtil;
import com.alibaba.csp.sentinel.Constants;

import com.sun.management.OperatingSystemMXBean;

/**
* @author jialiang.linjl
*/
public class SystemStatusListener implements Runnable {

volatile double currentLoad = -1;
volatile double currentCpuUsage = -1;

volatile String reason = StringUtil.EMPTY;

Expand All @@ -37,20 +39,33 @@ public double getSystemAverageLoad() {
return currentLoad;
}

public double getCpuUsage() {
return currentCpuUsage;
}

@Override
public void run() {
try {
if (!SystemRuleManager.getCheckSystemStatus()) {
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();
if (currentLoad > SystemRuleManager.getHighestSystemLoad()) {
sb.append("load:").append(currentLoad).append(";");
sb.append("cpu:").append(currentCpuUsage).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(";");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ private static void initSystemRule() {
SystemRule rule = new SystemRule();
// max load is 3
rule.setHighestSystemLoad(3.0);
// max cpu usage is 60%
rule.setHighestCpuUsage(0.6);
// max avg rt of all request is 10 ms
rule.setAvgRt(10);
// max total qps is 20
Expand Down