Browse Source

Make the value of RT_MAX_EXCEED_N in DegradeRule configurable (#789)

- Add two attributes in DegradeRule: rtSlowRequestAmount and minRequestAmount
master
Lin.Liang Eric Zhao 5 years ago
parent
commit
2eecd3ac6a
4 changed files with 133 additions and 38 deletions
  1. +4
    -0
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/RuleConstant.java
  2. +56
    -18
      sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeRule.java
  3. +67
    -15
      sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeTest.java
  4. +6
    -5
      sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/degrade/ExceptionRatioDegradeDemo.java

+ 4
- 0
sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/RuleConstant.java View File

@@ -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;




+ 56
- 18
sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeRule.java View File

@@ -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 < RT_MAX_EXCEED_N) {
// if total qps less than minRequestAmount, pass.
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() +
", 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 static final class ResetTask implements Runnable {


private DegradeRule rule; private DegradeRule rule;


+ 67
- 15
sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeTest.java View File

@@ -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);


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)); 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));


}

} }

+ 6
- 5
sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/degrade/ExceptionRatioDegradeDemo.java View File

@@ -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…
Cancel
Save