From 2eecd3ac6aa6f4574c531040131f4c20fa8c0edf Mon Sep 17 00:00:00 2001 From: "Lin.Liang" <546648227@qq.com> Date: Fri, 14 Jun 2019 17:42:03 +0800 Subject: [PATCH] Make the value of RT_MAX_EXCEED_N in DegradeRule configurable (#789) - Add two attributes in DegradeRule: rtSlowRequestAmount and minRequestAmount --- .../sentinel/slots/block/RuleConstant.java | 4 + .../slots/block/degrade/DegradeRule.java | 74 +++++++++++++---- .../slots/block/degrade/DegradeTest.java | 82 +++++++++++++++---- .../degrade/ExceptionRatioDegradeDemo.java | 11 +-- 4 files changed, 133 insertions(+), 38 deletions(-) diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/RuleConstant.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/RuleConstant.java index 978b169f..ee9fdc25 100755 --- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/RuleConstant.java +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/RuleConstant.java @@ -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; diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeRule.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeRule.java index f29c42d1..1d547163 100755 --- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeRule.java +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeRule.java @@ -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; + /** *
* 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; diff --git a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeTest.java b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeTest.java index b2518a80..75668c0b 100755 --- a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeTest.java +++ b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeTest.java @@ -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); - when(cn.successQps()).thenReturn(8d); - // Will fail. + // 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.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)); + + + } + } diff --git a/sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/degrade/ExceptionRatioDegradeDemo.java b/sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/degrade/ExceptionRatioDegradeDemo.java index 8007908c..c84756aa 100755 --- a/sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/degrade/ExceptionRatioDegradeDemo.java +++ b/sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/degrade/ExceptionRatioDegradeDemo.java @@ -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; + /** *
* 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); }