Make the value of RT_MAX_EXCEED_N in DegradeRule configurable (#789)
- Add two attributes in DegradeRule: rtSlowRequestAmount and minRequestAmount
This commit is contained in:
parent
e6e27c6faa
commit
2eecd3ac6a
|
|
@ -36,6 +36,10 @@ 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_GRADE_RT_MAX_EXCEED_N = 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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package com.alibaba.csp.sentinel.slots.block.degrade;
|
package com.alibaba.csp.sentinel.slots.block.degrade;
|
||||||
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.concurrent.NamedThreadFactory;
|
import com.alibaba.csp.sentinel.concurrent.NamedThreadFactory;
|
||||||
import com.alibaba.csp.sentinel.context.Context;
|
import com.alibaba.csp.sentinel.context.Context;
|
||||||
import com.alibaba.csp.sentinel.node.ClusterNode;
|
import com.alibaba.csp.sentinel.node.ClusterNode;
|
||||||
|
|
@ -29,6 +23,12 @@ import com.alibaba.csp.sentinel.slots.block.AbstractRule;
|
||||||
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
|
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
|
||||||
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
|
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Degrade is used when the resources are in an unstable state, these resources
|
* Degrade is used when the resources are in an unstable state, these resources
|
||||||
|
|
@ -55,7 +55,15 @@ import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
|
||||||
*/
|
*/
|
||||||
public class DegradeRule extends AbstractRule {
|
public class DegradeRule extends AbstractRule {
|
||||||
|
|
||||||
private static final int RT_MAX_EXCEED_N = 5;
|
/**
|
||||||
|
* 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(
|
||||||
|
|
@ -137,7 +145,7 @@ public class DegradeRule extends AbstractRule {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DegradeRule that = (DegradeRule)o;
|
DegradeRule that = (DegradeRule) o;
|
||||||
|
|
||||||
if (count != that.count) {
|
if (count != that.count) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -148,6 +156,13 @@ public class DegradeRule extends AbstractRule {
|
||||||
if (grade != that.grade) {
|
if (grade != that.grade) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (rtSlowRequestAmount != that.rtSlowRequestAmount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (minRequestAmount != that.minRequestAmount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,6 +172,8 @@ public class DegradeRule extends AbstractRule {
|
||||||
result = 31 * result + new Double(count).hashCode();
|
result = 31 * result + new Double(count).hashCode();
|
||||||
result = 31 * result + timeWindow;
|
result = 31 * result + timeWindow;
|
||||||
result = 31 * result + grade;
|
result = 31 * result + grade;
|
||||||
|
result = 31 * result + rtSlowRequestAmount;
|
||||||
|
result = 31 * result + minRequestAmount;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,20 +196,21 @@ public class DegradeRule extends AbstractRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sentinel will degrade the service only if count exceeds.
|
// Sentinel will degrade the service only if count exceeds.
|
||||||
if (passCount.incrementAndGet() < RT_MAX_EXCEED_N) {
|
if (passCount.incrementAndGet() < rtSlowRequestAmount) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (grade == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) {
|
} else if (grade == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) {
|
||||||
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 RT_MAX_EXCEED_N, pass.
|
// if total qps less than minRequestAmount, pass.
|
||||||
if (total < RT_MAX_EXCEED_N) {
|
if (total < minRequestAmount) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//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 < RT_MAX_EXCEED_N) {
|
if (realSuccess <= 0 && exception < minRequestAmount) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -214,17 +232,37 @@ public class DegradeRule extends AbstractRule {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "DegradeRule{" +
|
return "DegradeRule{" +
|
||||||
"resource=" + getResource() +
|
"resource=" + getResource() +
|
||||||
", grade=" + grade +
|
", grade=" + grade +
|
||||||
", count=" + count +
|
", count=" + count +
|
||||||
", limitApp=" + getLimitApp() +
|
", limitApp=" + getLimitApp() +
|
||||||
", timeWindow=" + timeWindow +
|
", 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;
|
||||||
|
|
|
||||||
|
|
@ -15,14 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package com.alibaba.csp.sentinel.slots.block.degrade;
|
package com.alibaba.csp.sentinel.slots.block.degrade;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.EntryType;
|
import com.alibaba.csp.sentinel.EntryType;
|
||||||
import com.alibaba.csp.sentinel.context.Context;
|
import com.alibaba.csp.sentinel.context.Context;
|
||||||
import com.alibaba.csp.sentinel.node.ClusterNode;
|
import com.alibaba.csp.sentinel.node.ClusterNode;
|
||||||
|
|
@ -30,6 +22,14 @@ import com.alibaba.csp.sentinel.node.DefaultNode;
|
||||||
import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper;
|
import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper;
|
||||||
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
|
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
|
||||||
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
|
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author jialiang.linjl
|
* @author jialiang.linjl
|
||||||
|
|
@ -47,12 +47,16 @@ public class DegradeTest {
|
||||||
when(node.getClusterNode()).thenReturn(cn);
|
when(node.getClusterNode()).thenReturn(cn);
|
||||||
when(cn.avgRt()).thenReturn(2d);
|
when(cn.avgRt()).thenReturn(2d);
|
||||||
|
|
||||||
|
int rtSlowRequestAmount = 10;
|
||||||
DegradeRule rule = new DegradeRule();
|
DegradeRule rule = new DegradeRule();
|
||||||
rule.setCount(1);
|
rule.setCount(1);
|
||||||
rule.setResource(key);
|
rule.setResource(key);
|
||||||
rule.setTimeWindow(2);
|
rule.setTimeWindow(2);
|
||||||
|
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
|
||||||
|
rule.setRtSlowRequestAmount(rtSlowRequestAmount);
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
//Will true
|
||||||
|
for (int i = 0; i < rtSlowRequestAmount - 1; i++) {
|
||||||
assertTrue(rule.passCheck(context, node, 1));
|
assertTrue(rule.passCheck(context, node, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,9 +73,6 @@ public class DegradeTest {
|
||||||
public void testExceptionRatioModeDegrade() throws Throwable {
|
public void testExceptionRatioModeDegrade() throws Throwable {
|
||||||
String key = "test_degrade_exception_ratio";
|
String key = "test_degrade_exception_ratio";
|
||||||
ClusterNode cn = mock(ClusterNode.class);
|
ClusterNode cn = mock(ClusterNode.class);
|
||||||
when(cn.exceptionQps()).thenReturn(2d);
|
|
||||||
// Indicates that there are QPS more than min threshold.
|
|
||||||
when(cn.totalQps()).thenReturn(12d);
|
|
||||||
ClusterBuilderSlot.getClusterNodeMap().put(new StringResourceWrapper(key, EntryType.IN), cn);
|
ClusterBuilderSlot.getClusterNodeMap().put(new StringResourceWrapper(key, EntryType.IN), cn);
|
||||||
|
|
||||||
Context context = mock(Context.class);
|
Context context = mock(Context.class);
|
||||||
|
|
@ -83,17 +84,39 @@ public class DegradeTest {
|
||||||
rule.setResource(key);
|
rule.setResource(key);
|
||||||
rule.setTimeWindow(2);
|
rule.setTimeWindow(2);
|
||||||
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
|
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
|
||||||
|
rule.setMinRequestAmount(20);
|
||||||
|
|
||||||
|
|
||||||
|
// Will true. While totalQps < minRequestAmount
|
||||||
|
when(cn.totalQps()).thenReturn(8d);
|
||||||
|
assertTrue(rule.passCheck(context, node, 1));
|
||||||
|
|
||||||
|
// Will true.
|
||||||
|
when(cn.totalQps()).thenReturn(21d);
|
||||||
|
when(cn.successQps()).thenReturn(9d);
|
||||||
|
when(cn.exceptionQps()).thenReturn(9d);
|
||||||
|
assertTrue(rule.passCheck(context, node, 1));
|
||||||
|
|
||||||
|
|
||||||
|
// Will true. While totalQps > minRequestAmount and exceptionRation < count
|
||||||
|
when(cn.totalQps()).thenReturn(100d);
|
||||||
|
when(cn.successQps()).thenReturn(90d);
|
||||||
|
when(cn.exceptionQps()).thenReturn(10d);
|
||||||
|
assertTrue(rule.passCheck(context, node, 1));
|
||||||
|
|
||||||
|
// Will fail. While totalQps > minRequestAmount and exceptionRation > count
|
||||||
|
rule.setMinRequestAmount(5);
|
||||||
|
when(cn.totalQps()).thenReturn(12d);
|
||||||
when(cn.successQps()).thenReturn(8d);
|
when(cn.successQps()).thenReturn(8d);
|
||||||
|
when(cn.exceptionQps()).thenReturn(6d);
|
||||||
// Will fail.
|
|
||||||
assertFalse(rule.passCheck(context, node, 1));
|
assertFalse(rule.passCheck(context, node, 1));
|
||||||
|
|
||||||
// Restore from the degrade timeout.
|
// Restore from the degrade timeout.
|
||||||
TimeUnit.MILLISECONDS.sleep(2200);
|
TimeUnit.MILLISECONDS.sleep(2200);
|
||||||
|
|
||||||
when(cn.successQps()).thenReturn(20d);
|
|
||||||
// Will pass.
|
// Will pass.
|
||||||
|
when(cn.totalQps()).thenReturn(106d);
|
||||||
|
when(cn.successQps()).thenReturn(100d);
|
||||||
assertTrue(rule.passCheck(context, node, 1));
|
assertTrue(rule.passCheck(context, node, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,4 +150,33 @@ public class DegradeTest {
|
||||||
assertTrue(rule.passCheck(context, node, 1));
|
assertTrue(rule.passCheck(context, node, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEquals() {
|
||||||
|
DegradeRule degradeRule1 = new DegradeRule();
|
||||||
|
DegradeRule degradeRule2 = new DegradeRule();
|
||||||
|
assertTrue(degradeRule1.equals(degradeRule2));
|
||||||
|
|
||||||
|
int rtSlowRequestAmount = 10;
|
||||||
|
int minRequestAmount = 20;
|
||||||
|
double count = 1.0;
|
||||||
|
int timeWindow = 2;
|
||||||
|
degradeRule1.setRtSlowRequestAmount(rtSlowRequestAmount);
|
||||||
|
degradeRule1.setMinRequestAmount(minRequestAmount);
|
||||||
|
degradeRule1.setCount(count);
|
||||||
|
degradeRule1.setTimeWindow(timeWindow);
|
||||||
|
degradeRule1.setGrade(RuleConstant.DEGRADE_GRADE_RT);
|
||||||
|
|
||||||
|
degradeRule2.setRtSlowRequestAmount(rtSlowRequestAmount);
|
||||||
|
degradeRule2.setMinRequestAmount(minRequestAmount);
|
||||||
|
degradeRule2.setCount(count);
|
||||||
|
degradeRule2.setGrade(RuleConstant.DEGRADE_GRADE_RT);
|
||||||
|
degradeRule2.setTimeWindow(timeWindow);
|
||||||
|
assertTrue(degradeRule1.equals(degradeRule2));
|
||||||
|
|
||||||
|
degradeRule2.setMinRequestAmount(100);
|
||||||
|
assertFalse(degradeRule1.equals(degradeRule2));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package com.alibaba.csp.sentinel.demo.degrade;
|
package com.alibaba.csp.sentinel.demo.degrade;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.Entry;
|
import com.alibaba.csp.sentinel.Entry;
|
||||||
import com.alibaba.csp.sentinel.SphU;
|
import com.alibaba.csp.sentinel.SphU;
|
||||||
import com.alibaba.csp.sentinel.Tracer;
|
import com.alibaba.csp.sentinel.Tracer;
|
||||||
|
|
@ -29,6 +24,11 @@ import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
|
||||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
|
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
|
||||||
import com.alibaba.csp.sentinel.util.TimeUtil;
|
import com.alibaba.csp.sentinel.util.TimeUtil;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Degrade is used when the resources are in an unstable state, these resources
|
* Degrade is used when the resources are in an unstable state, these resources
|
||||||
|
|
@ -115,6 +115,7 @@ public class ExceptionRatioDegradeDemo {
|
||||||
rule.setCount(0.1);
|
rule.setCount(0.1);
|
||||||
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
|
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
|
||||||
rule.setTimeWindow(10);
|
rule.setTimeWindow(10);
|
||||||
|
rule.setMinRequestAmount(20);
|
||||||
rules.add(rule);
|
rules.add(rule);
|
||||||
DegradeRuleManager.loadRules(rules);
|
DegradeRuleManager.loadRules(rules);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue