Bläddra i källkod

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 år sedan
förälder
incheckning
2eecd3ac6a
4 ändrade filer med 133 tillägg och 38 borttagningar
  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 Visa fil

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



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

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


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

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


}

}

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

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


Laddar…
Avbryt
Spara