diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/degrade/circuitbreaker/ResponseTimeCircuitBreaker.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/degrade/circuitbreaker/ResponseTimeCircuitBreaker.java index 51f81316..2ab98d4d 100644 --- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/degrade/circuitbreaker/ResponseTimeCircuitBreaker.java +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/degrade/circuitbreaker/ResponseTimeCircuitBreaker.java @@ -19,7 +19,6 @@ import java.util.List; import com.alibaba.csp.sentinel.Entry; import com.alibaba.csp.sentinel.context.Context; -import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; import com.alibaba.csp.sentinel.slots.block.RuleConstant; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; import com.alibaba.csp.sentinel.slots.statistic.base.LeapArray; @@ -34,6 +33,8 @@ import com.alibaba.csp.sentinel.util.TimeUtil; */ public class ResponseTimeCircuitBreaker extends AbstractCircuitBreaker { + private static final double SLOW_REQUEST_RATIO_MAX_VALUE = 1.0d; + private final long maxAllowedRt; private final double maxSlowRequestRatio; private final int minRequestAmount; @@ -110,6 +111,10 @@ public class ResponseTimeCircuitBreaker extends AbstractCircuitBreaker { if (currentRatio > maxSlowRequestRatio) { transformToOpen(currentRatio); } + if (Double.compare(currentRatio, maxSlowRequestRatio) == 0 && + Double.compare(maxSlowRequestRatio, SLOW_REQUEST_RATIO_MAX_VALUE) == 0) { + transformToOpen(currentRatio); + } } static class SlowRequestCounter { diff --git a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/circuitbreaker/ResponseTimeCircuitBreakerTest.java b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/circuitbreaker/ResponseTimeCircuitBreakerTest.java new file mode 100644 index 00000000..66dd4691 --- /dev/null +++ b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/circuitbreaker/ResponseTimeCircuitBreakerTest.java @@ -0,0 +1,58 @@ +package com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker; + +import com.alibaba.csp.sentinel.slots.block.RuleConstant; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; +import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collections; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author xierz + * @date 2020/10/4 + */ +public class ResponseTimeCircuitBreakerTest extends AbstractTimeBasedTest { + @Before + public void setUp() { + DegradeRuleManager.loadRules(new ArrayList()); + } + + @After + public void tearDown() throws Exception { + DegradeRuleManager.loadRules(new ArrayList()); + } + + @Test + public void testMaxSlowRatioThreshold() { + String resource = "testMaxSlowRatioThreshold"; + DegradeRule rule = new DegradeRule("resource") + .setCount(10) + .setGrade(RuleConstant.DEGRADE_GRADE_RT) + .setMinRequestAmount(3) + .setSlowRatioThreshold(1) + .setStatIntervalMs(5000) + .setTimeWindow(5); + rule.setResource(resource); + DegradeRuleManager.loadRules(Collections.singletonList(rule)); + + assertTrue(entryAndSleepFor(resource, 20)); + assertTrue(entryAndSleepFor(resource, 20)); + assertTrue(entryAndSleepFor(resource, 20)); + + // should be blocked, cause 3/3 requests' rt is bigger than max rt. + assertFalse(entryAndSleepFor(resource,20)); + sleep(1000); + assertFalse(entryAndSleepFor(resource,20)); + sleep(4000); + + assertTrue(entryAndSleepFor(resource, 20)); + } + +}