Refine the DegradeRule and add validating logic for the two new attributes
- improvement of #789 Signed-off-by: Eric Zhao <sczyh16@gmail.com>
This commit is contained in:
parent
254ccbbdc5
commit
00f116e344
|
|
@ -36,9 +36,8 @@ public final class RuleConstant {
|
||||||
*/
|
*/
|
||||||
public static final int DEGRADE_GRADE_EXCEPTION_COUNT = 2;
|
public static final int DEGRADE_GRADE_EXCEPTION_COUNT = 2;
|
||||||
|
|
||||||
|
public static final int DEGRADE_DEFAULT_SLOW_REQUEST_AMOUNT = 5;
|
||||||
public static final int DEGRADE_GRADE_RT_MAX_EXCEED_N = 5;
|
public static final int DEGRADE_DEFAULT_MIN_REQUEST_AMOUNT = 5;
|
||||||
public static final int DEGRADE_GRADE_MIN_REQUEST_EXCEED_N = 5;
|
|
||||||
|
|
||||||
public static final int AUTHORITY_WHITE = 0;
|
public static final int AUTHORITY_WHITE = 0;
|
||||||
public static final int AUTHORITY_BLACK = 1;
|
public static final int AUTHORITY_BLACK = 1;
|
||||||
|
|
|
||||||
|
|
@ -55,16 +55,6 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||||
*/
|
*/
|
||||||
public class DegradeRule extends AbstractRule {
|
public class DegradeRule extends AbstractRule {
|
||||||
|
|
||||||
/**
|
|
||||||
* minimum number of consecutive slow requests that can trigger RT circuit breaking
|
|
||||||
*/
|
|
||||||
private int rtSlowRequestAmount = RuleConstant.DEGRADE_GRADE_RT_MAX_EXCEED_N;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* minimum number of requests (in an active statistic time span) that can trigger circuit breaking
|
|
||||||
*/
|
|
||||||
private int minRequestAmount = RuleConstant.DEGRADE_GRADE_MIN_REQUEST_EXCEED_N;
|
|
||||||
|
|
||||||
@SuppressWarnings("PMD.ThreadPoolCreationRule")
|
@SuppressWarnings("PMD.ThreadPoolCreationRule")
|
||||||
private static ScheduledExecutorService pool = Executors.newScheduledThreadPool(
|
private static ScheduledExecutorService pool = Executors.newScheduledThreadPool(
|
||||||
Runtime.getRuntime().availableProcessors(), new NamedThreadFactory("sentinel-degrade-reset-task", true));
|
Runtime.getRuntime().availableProcessors(), new NamedThreadFactory("sentinel-degrade-reset-task", true));
|
||||||
|
|
@ -86,11 +76,23 @@ public class DegradeRule extends AbstractRule {
|
||||||
private int timeWindow;
|
private int timeWindow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Degrade strategy (0: average RT, 1: exception ratio).
|
* Degrade strategy (0: average RT, 1: exception ratio, 2: exception count).
|
||||||
*/
|
*/
|
||||||
private int grade = RuleConstant.DEGRADE_GRADE_RT;
|
private int grade = RuleConstant.DEGRADE_GRADE_RT;
|
||||||
|
|
||||||
private final AtomicBoolean cut = new AtomicBoolean(false);
|
/**
|
||||||
|
* Minimum number of consecutive slow requests that can trigger RT circuit breaking.
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
private int rtSlowRequestAmount = RuleConstant.DEGRADE_DEFAULT_SLOW_REQUEST_AMOUNT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum number of requests (in an active statistic time span) that can trigger circuit breaking.
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
private int minRequestAmount = RuleConstant.DEGRADE_DEFAULT_MIN_REQUEST_AMOUNT;
|
||||||
|
|
||||||
public int getGrade() {
|
public int getGrade() {
|
||||||
return grade;
|
return grade;
|
||||||
|
|
@ -101,8 +103,6 @@ public class DegradeRule extends AbstractRule {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AtomicLong passCount = new AtomicLong(0);
|
|
||||||
|
|
||||||
public double getCount() {
|
public double getCount() {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
@ -112,18 +112,6 @@ public class DegradeRule extends AbstractRule {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isCut() {
|
|
||||||
return cut.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setCut(boolean cut) {
|
|
||||||
this.cut.set(cut);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AtomicLong getPassCount() {
|
|
||||||
return passCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTimeWindow() {
|
public int getTimeWindow() {
|
||||||
return timeWindow;
|
return timeWindow;
|
||||||
}
|
}
|
||||||
|
|
@ -133,37 +121,35 @@ public class DegradeRule extends AbstractRule {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getRtSlowRequestAmount() {
|
||||||
|
return rtSlowRequestAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DegradeRule setRtSlowRequestAmount(int rtSlowRequestAmount) {
|
||||||
|
this.rtSlowRequestAmount = rtSlowRequestAmount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMinRequestAmount() {
|
||||||
|
return minRequestAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DegradeRule setMinRequestAmount(int minRequestAmount) {
|
||||||
|
this.minRequestAmount = minRequestAmount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) {
|
if (this == o) { return true; }
|
||||||
return true;
|
if (o == null || getClass() != o.getClass()) { return false; }
|
||||||
}
|
if (!super.equals(o)) { return false; }
|
||||||
if (!(o instanceof DegradeRule)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!super.equals(o)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DegradeRule that = (DegradeRule) o;
|
DegradeRule that = (DegradeRule) o;
|
||||||
|
return Double.compare(that.count, count) == 0 &&
|
||||||
if (count != that.count) {
|
timeWindow == that.timeWindow &&
|
||||||
return false;
|
grade == that.grade &&
|
||||||
}
|
rtSlowRequestAmount == that.rtSlowRequestAmount &&
|
||||||
if (timeWindow != that.timeWindow) {
|
minRequestAmount == that.minRequestAmount;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (grade != that.grade) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (rtSlowRequestAmount != that.rtSlowRequestAmount) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (minRequestAmount != that.minRequestAmount) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -177,6 +163,24 @@ public class DegradeRule extends AbstractRule {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "DegradeRule{" +
|
||||||
|
"resource=" + getResource() +
|
||||||
|
", grade=" + grade +
|
||||||
|
", count=" + count +
|
||||||
|
", limitApp=" + getLimitApp() +
|
||||||
|
", timeWindow=" + timeWindow +
|
||||||
|
", rtSlowRequestAmount=" + rtSlowRequestAmount +
|
||||||
|
", minRequestAmount=" + minRequestAmount +
|
||||||
|
"}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal implementation (will be deprecated and moved outside).
|
||||||
|
|
||||||
|
private AtomicLong passCount = new AtomicLong(0);
|
||||||
|
private final AtomicBoolean cut = new AtomicBoolean(false);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean passCheck(Context context, DefaultNode node, int acquireCount, Object... args) {
|
public boolean passCheck(Context context, DefaultNode node, int acquireCount, Object... args) {
|
||||||
if (cut.get()) {
|
if (cut.get()) {
|
||||||
|
|
@ -203,12 +207,13 @@ public class DegradeRule extends AbstractRule {
|
||||||
double exception = clusterNode.exceptionQps();
|
double exception = clusterNode.exceptionQps();
|
||||||
double success = clusterNode.successQps();
|
double success = clusterNode.successQps();
|
||||||
double total = clusterNode.totalQps();
|
double total = clusterNode.totalQps();
|
||||||
// if total qps less than minRequestAmount, pass.
|
// If total amount is less than minRequestAmount, the request will pass.
|
||||||
if (total < minRequestAmount) {
|
if (total < minRequestAmount) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//in the same aligned statistic time window, success (aka. completed count) = exception count + non-exception count (realSuccess)
|
// In the same aligned statistic time window,
|
||||||
|
// "success" (aka. completed count) = exception count + non-exception count (realSuccess)
|
||||||
double realSuccess = success - exception;
|
double realSuccess = success - exception;
|
||||||
if (realSuccess <= 0 && exception < minRequestAmount) {
|
if (realSuccess <= 0 && exception < minRequestAmount) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -232,37 +237,6 @@ public class DegradeRule extends AbstractRule {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "DegradeRule{" +
|
|
||||||
"resource=" + getResource() +
|
|
||||||
", grade=" + grade +
|
|
||||||
", count=" + count +
|
|
||||||
", limitApp=" + getLimitApp() +
|
|
||||||
", timeWindow=" + timeWindow +
|
|
||||||
", rtSlowRequestAmount=" + rtSlowRequestAmount +
|
|
||||||
", minRequestAmount=" + minRequestAmount +
|
|
||||||
"}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRtSlowRequestAmount() {
|
|
||||||
return rtSlowRequestAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRtSlowRequestAmount(int rtSlowRequestAmount) {
|
|
||||||
this.rtSlowRequestAmount = rtSlowRequestAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMinRequestAmount() {
|
|
||||||
return minRequestAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMinRequestAmount(int minRequestAmount) {
|
|
||||||
this.minRequestAmount = minRequestAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static final class ResetTask implements Runnable {
|
private static final class ResetTask implements Runnable {
|
||||||
|
|
||||||
private DegradeRule rule;
|
private DegradeRule rule;
|
||||||
|
|
@ -273,9 +247,8 @@ public class DegradeRule extends AbstractRule {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
rule.getPassCount().set(0);
|
rule.passCount.set(0);
|
||||||
rule.cut.set(false);
|
rule.cut.set(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -211,17 +211,23 @@ public final class DegradeRuleManager {
|
||||||
if (!baseValid) {
|
if (!baseValid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Warn for RT mode that exceeds the {@code TIME_DROP_VALVE}.
|
|
||||||
int maxAllowedRt = Constants.TIME_DROP_VALVE;
|
int maxAllowedRt = Constants.TIME_DROP_VALVE;
|
||||||
if (rule.getGrade() == RuleConstant.DEGRADE_GRADE_RT && rule.getCount() > maxAllowedRt) {
|
if (rule.getGrade() == RuleConstant.DEGRADE_GRADE_RT) {
|
||||||
RecordLog.warn(String.format("[DegradeRuleManager] WARN: setting large RT threshold (%.1f ms) in RT mode"
|
if (rule.getRtSlowRequestAmount() <= 0) {
|
||||||
+ " will not take effect since it exceeds the max allowed value (%d ms)", rule.getCount(),
|
|
||||||
maxAllowedRt));
|
|
||||||
}
|
|
||||||
// Check exception ratio mode.
|
|
||||||
if (rule.getGrade() == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO && rule.getCount() > 1) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Warn for RT mode that exceeds the {@code TIME_DROP_VALVE}.
|
||||||
|
if (rule.getCount() > maxAllowedRt) {
|
||||||
|
RecordLog.warn(String.format("[DegradeRuleManager] WARN: setting large RT threshold (%.1f ms)"
|
||||||
|
+ " in RT mode will not take effect since it exceeds the max allowed value (%d ms)",
|
||||||
|
rule.getCount(), maxAllowedRt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check exception ratio mode.
|
||||||
|
if (rule.getGrade() == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) {
|
||||||
|
return rule.getCount() <= 1 && rule.getMinRequestAmount() > 0;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,23 @@ public class DegradeRuleManagerTest {
|
||||||
.setCount(-3)
|
.setCount(-3)
|
||||||
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT)
|
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT)
|
||||||
.setTimeWindow(2);
|
.setTimeWindow(2);
|
||||||
|
DegradeRule rule5 = new DegradeRule("Sentinel")
|
||||||
|
.setCount(97)
|
||||||
|
.setGrade(RuleConstant.DEGRADE_GRADE_RT)
|
||||||
|
.setTimeWindow(15)
|
||||||
|
.setRtSlowRequestAmount(0);
|
||||||
|
DegradeRule rule6 = new DegradeRule("Sentinel")
|
||||||
|
.setCount(0.93d)
|
||||||
|
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
|
||||||
|
.setTimeWindow(20)
|
||||||
|
.setMinRequestAmount(0);
|
||||||
assertFalse(DegradeRuleManager.isValidRule(rule1));
|
assertFalse(DegradeRuleManager.isValidRule(rule1));
|
||||||
assertFalse(DegradeRuleManager.isValidRule(rule2));
|
assertFalse(DegradeRuleManager.isValidRule(rule2));
|
||||||
assertFalse(DegradeRuleManager.isValidRule(rule3));
|
assertFalse(DegradeRuleManager.isValidRule(rule3));
|
||||||
assertTrue(DegradeRuleManager.isValidRule(rule3.setCount(1.0d)));
|
assertTrue(DegradeRuleManager.isValidRule(rule3.setCount(1.0d)));
|
||||||
assertTrue(DegradeRuleManager.isValidRule(rule3.setCount(0.0d)));
|
assertTrue(DegradeRuleManager.isValidRule(rule3.setCount(0.0d)));
|
||||||
assertFalse(DegradeRuleManager.isValidRule(rule4));
|
assertFalse(DegradeRuleManager.isValidRule(rule4));
|
||||||
|
assertFalse(DegradeRuleManager.isValidRule(rule5));
|
||||||
|
assertFalse(DegradeRuleManager.isValidRule(rule6));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue