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_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_BLACK = 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,12 +15,6 @@
|
|||
*/
|
||||
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.context.Context;
|
||||
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.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>
|
||||
* 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 {
|
||||
|
||||
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")
|
||||
private static ScheduledExecutorService pool = Executors.newScheduledThreadPool(
|
||||
|
|
@ -137,7 +145,7 @@ public class DegradeRule extends AbstractRule {
|
|||
return false;
|
||||
}
|
||||
|
||||
DegradeRule that = (DegradeRule)o;
|
||||
DegradeRule that = (DegradeRule) o;
|
||||
|
||||
if (count != that.count) {
|
||||
return false;
|
||||
|
|
@ -148,6 +156,13 @@ public class DegradeRule extends AbstractRule {
|
|||
if (grade != that.grade) {
|
||||
return false;
|
||||
}
|
||||
if (rtSlowRequestAmount != that.rtSlowRequestAmount) {
|
||||
return false;
|
||||
}
|
||||
if (minRequestAmount != that.minRequestAmount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -157,6 +172,8 @@ public class DegradeRule extends AbstractRule {
|
|||
result = 31 * result + new Double(count).hashCode();
|
||||
result = 31 * result + timeWindow;
|
||||
result = 31 * result + grade;
|
||||
result = 31 * result + rtSlowRequestAmount;
|
||||
result = 31 * result + minRequestAmount;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -179,20 +196,21 @@ public class DegradeRule extends AbstractRule {
|
|||
}
|
||||
|
||||
// Sentinel will degrade the service only if count exceeds.
|
||||
if (passCount.incrementAndGet() < RT_MAX_EXCEED_N) {
|
||||
if (passCount.incrementAndGet() < rtSlowRequestAmount) {
|
||||
return true;
|
||||
}
|
||||
} else if (grade == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) {
|
||||
double exception = clusterNode.exceptionQps();
|
||||
double success = clusterNode.successQps();
|
||||
double total = clusterNode.totalQps();
|
||||
// if total qps less than RT_MAX_EXCEED_N, pass.
|
||||
if (total < RT_MAX_EXCEED_N) {
|
||||
// if total qps less than minRequestAmount, pass.
|
||||
if (total < minRequestAmount) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//in the same aligned statistic time window, success (aka. completed count) = exception count + non-exception count (realSuccess)
|
||||
double realSuccess = success - exception;
|
||||
if (realSuccess <= 0 && exception < RT_MAX_EXCEED_N) {
|
||||
if (realSuccess <= 0 && exception < minRequestAmount) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -214,17 +232,37 @@ public class DegradeRule extends AbstractRule {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DegradeRule{" +
|
||||
"resource=" + getResource() +
|
||||
", grade=" + grade +
|
||||
", count=" + count +
|
||||
", limitApp=" + getLimitApp() +
|
||||
", timeWindow=" + timeWindow +
|
||||
"}";
|
||||
"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 DegradeRule rule;
|
||||
|
|
|
|||
|
|
@ -15,14 +15,6 @@
|
|||
*/
|
||||
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.context.Context;
|
||||
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.slots.block.RuleConstant;
|
||||
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
|
||||
|
|
@ -47,12 +47,16 @@ public class DegradeTest {
|
|||
when(node.getClusterNode()).thenReturn(cn);
|
||||
when(cn.avgRt()).thenReturn(2d);
|
||||
|
||||
int rtSlowRequestAmount = 10;
|
||||
DegradeRule rule = new DegradeRule();
|
||||
rule.setCount(1);
|
||||
rule.setResource(key);
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
@ -69,9 +73,6 @@ public class DegradeTest {
|
|||
public void testExceptionRatioModeDegrade() throws Throwable {
|
||||
String key = "test_degrade_exception_ratio";
|
||||
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);
|
||||
|
||||
Context context = mock(Context.class);
|
||||
|
|
@ -83,17 +84,39 @@ public class DegradeTest {
|
|||
rule.setResource(key);
|
||||
rule.setTimeWindow(2);
|
||||
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);
|
||||
|
||||
// Will fail.
|
||||
when(cn.exceptionQps()).thenReturn(6d);
|
||||
assertFalse(rule.passCheck(context, node, 1));
|
||||
|
||||
// Restore from the degrade timeout.
|
||||
TimeUnit.MILLISECONDS.sleep(2200);
|
||||
|
||||
when(cn.successQps()).thenReturn(20d);
|
||||
// Will pass.
|
||||
when(cn.totalQps()).thenReturn(106d);
|
||||
when(cn.successQps()).thenReturn(100d);
|
||||
assertTrue(rule.passCheck(context, node, 1));
|
||||
}
|
||||
|
||||
|
|
@ -127,4 +150,33 @@ public class DegradeTest {
|
|||
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;
|
||||
|
||||
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.SphU;
|
||||
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.util.TimeUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 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.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
|
||||
rule.setTimeWindow(10);
|
||||
rule.setMinRequestAmount(20);
|
||||
rules.add(rule);
|
||||
DegradeRuleManager.loadRules(rules);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue