Bladeren bron

Update demo for circuit breaking (DegradeRule)

Signed-off-by: Eric Zhao <sczyh16@gmail.com>
master
Eric Zhao 4 jaren geleden
bovenliggende
commit
19db20f00d
3 gewijzigde bestanden met toevoegingen van 155 en 321 verwijderingen
  1. +0
    -169
      sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/degrade/ExceptionCountDegradeDemo.java
  2. +76
    -72
      sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/degrade/ExceptionRatioCircuitBreakerDemo.java
  3. +79
    -80
      sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/degrade/SlowRatioCircuitBreakerDemo.java

+ 0
- 169
sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/degrade/ExceptionCountDegradeDemo.java Bestand weergeven

@@ -1,169 +0,0 @@
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;
import com.alibaba.csp.sentinel.slots.block.BlockException;
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.util.TimeUtil;

/**
* <p>
* Degrade is used when the resources are in an unstable state, these resources
* will be degraded within the next defined time window. There are three ways to
* measure whether a resource is stable or not:
* <ul>
* <li>
* Exception count: When the exception count in the last 60 seconds greats than
* or equals to the threshold, access to the resource will be blocked in the
* coming time window.
* </li>
* <li>
* Exception ratio, see {@link ExceptionRatioDegradeDemo}.
* </li>
* <li>
* For average response time, see {@link RtDegradeDemo}.
* </li>
* </ul>
* </p>
* <p>
* Note: When degrading by {@link RuleConstant#DEGRADE_GRADE_EXCEPTION_COUNT}, time window
* less than 60 seconds will not work as expected. Because the exception count is
* summed by minute, when a short time window elapsed, the degradation condition
* may still be satisfied.
* </p>
*
* @author Carpenter Lee
*/
public class ExceptionCountDegradeDemo {
private static final String KEY = "abc";

private static AtomicInteger total = new AtomicInteger();
private static AtomicInteger pass = new AtomicInteger();
private static AtomicInteger block = new AtomicInteger();
private static AtomicInteger bizException = new AtomicInteger();

private static volatile boolean stop = false;
private static final int threadCount = 1;
private static int seconds = 60 + 40;

public static void main(String[] args) throws Exception {
tick();
initDegradeRule();

for (int i = 0; i < threadCount; i++) {
Thread entryThread = new Thread(new Runnable() {

@Override
public void run() {
int count = 0;
while (true) {
count++;
Entry entry = null;
try {
Thread.sleep(20);
entry = SphU.entry(KEY);
// token acquired, means pass
pass.addAndGet(1);
if (count % 2 == 0) {
// biz code raise an exception.
throw new RuntimeException("throw runtime ");
}
} catch (BlockException e) {
block.addAndGet(1);
} catch (Throwable t) {
bizException.incrementAndGet();
Tracer.trace(t);
} finally {
total.addAndGet(1);
if (entry != null) {
entry.exit();
}
}
}
}

});
entryThread.setName("working-thread");
entryThread.start();
}

}

private static void initDegradeRule() {
List<DegradeRule> rules = new ArrayList<DegradeRule>();
DegradeRule rule = new DegradeRule();
rule.setResource(KEY);
// set limit exception count to 4
rule.setCount(4);
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
/**
* When degrading by {@link RuleConstant#DEGRADE_GRADE_EXCEPTION_COUNT}, time window
* less than 60 seconds will not work as expected. Because the exception count is
* summed by minute, when a short time window elapsed, the degradation condition
* may still be satisfied.
*/
rule.setTimeWindow(10);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}

private static void tick() {
Thread timer = new Thread(new TimerTask());
timer.setName("sentinel-timer-task");
timer.start();
}

static class TimerTask implements Runnable {
@Override
public void run() {
long start = System.currentTimeMillis();
System.out.println("begin to statistic!!!");
long oldTotal = 0;
long oldPass = 0;
long oldBlock = 0;
long oldBizException = 0;
while (!stop) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
}
long globalTotal = total.get();
long oneSecondTotal = globalTotal - oldTotal;
oldTotal = globalTotal;

long globalPass = pass.get();
long oneSecondPass = globalPass - oldPass;
oldPass = globalPass;

long globalBlock = block.get();
long oneSecondBlock = globalBlock - oldBlock;
oldBlock = globalBlock;

long globalBizException = bizException.get();
long oneSecondBizException = globalBizException - oldBizException;
oldBizException = globalBizException;

System.out.println(TimeUtil.currentTimeMillis() + ", oneSecondTotal:" + oneSecondTotal
+ ", oneSecondPass:" + oneSecondPass
+ ", oneSecondBlock:" + oneSecondBlock
+ ", oneSecondBizException:" + oneSecondBizException);
if (seconds-- <= 0) {
stop = true;
}
}
long cost = System.currentTimeMillis() - start;
System.out.println("time cost: " + cost + " ms");
System.out.println("total:" + total.get() + ", pass:" + pass.get()
+ ", block:" + block.get() + ", bizException:" + bizException.get());
System.exit(0);
}
}
}

sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/degrade/ExceptionRatioDegradeDemo.java → sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/degrade/ExceptionRatioCircuitBreakerDemo.java Bestand weergeven

@@ -19,41 +19,26 @@ import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.slots.block.BlockException;
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.slots.block.degrade.circuitbreaker.CircuitBreaker.State;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreakerStrategy;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.EventObserverRegistry;
import com.alibaba.csp.sentinel.util.TimeUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
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
* will be degraded within the next defined time window. There are three ways to
* measure whether a resource is stable or not:
* <ul>
* <li>
* Exception ratio: When the ratio of exception count per second and the success
* qps greats than or equals to the threshold, access to the resource will be blocked
* in the coming time window.
* </li>
* <li>
* Exception Count, see {@link ExceptionCountDegradeDemo}.
* </li>
* <li>
* For average response time, see {@link RtDegradeDemo}.
* </li>
* </ul>
* </p>
*
* @author jialiang.linjl
* @author Eric Zhao
*/
public class ExceptionRatioDegradeDemo {
public class ExceptionRatioCircuitBreakerDemo {

private static final String KEY = "abc";
private static final String KEY = "some_service";

private static AtomicInteger total = new AtomicInteger();
private static AtomicInteger pass = new AtomicInteger();
@@ -61,68 +46,87 @@ public class ExceptionRatioDegradeDemo {
private static AtomicInteger bizException = new AtomicInteger();

private static volatile boolean stop = false;
private static final int threadCount = 1;
private static int seconds = 60 + 40;
private static int seconds = 120;

public static void main(String[] args) throws Exception {
tick();
initDegradeRule();
for (int i = 0; i < threadCount; i++) {
Thread entryThread = new Thread(new Runnable() {
@Override
public void run() {
int count = 0;
while (true) {
count++;
Entry entry = null;
try {
Thread.sleep(20);
entry = SphU.entry(KEY);
// token acquired, means pass
pass.addAndGet(1);
if (count % 2 == 0) {
// biz code raise an exception.
throw new RuntimeException("throw runtime ");
}
} catch (BlockException e) {
block.addAndGet(1);
} catch (Throwable t) {
bizException.incrementAndGet();
Tracer.trace(t);
} finally {
total.addAndGet(1);
if (entry != null) {
entry.exit();
}
registerStateChangeObserver();
startTick();
final int concurrency = 8;
for (int i = 0; i < concurrency; i++) {
Thread entryThread = new Thread(() -> {
while (true) {
Entry entry = null;
try {
entry = SphU.entry(KEY);
sleep(ThreadLocalRandom.current().nextInt(5, 10));
pass.addAndGet(1);
// Error probability is 45%
if (ThreadLocalRandom.current().nextInt(0, 100) > 55) {
// biz code raise an exception.
throw new RuntimeException("oops");
}
} catch (BlockException e) {
block.addAndGet(1);
sleep(ThreadLocalRandom.current().nextInt(5, 10));
} catch (Throwable t) {
bizException.incrementAndGet();
// It's required to record exception here manually.
Tracer.traceEntry(t, entry);
} finally {
total.addAndGet(1);
if (entry != null) {
entry.exit();
}
}
}

});
entryThread.setName("working-thread");
entryThread.setName("sentinel-simulate-traffic-task-" + i);
entryThread.start();
}
}

private static void registerStateChangeObserver() {
EventObserverRegistry.getInstance().addStateChangeObserver("logging",
(prevState, newState, rule, snapshotValue) -> {
if (newState == State.OPEN) {
System.err.println(String.format("%s -> OPEN at %d, snapshotValue=%.2f", prevState.name(),
TimeUtil.currentTimeMillis(), snapshotValue));
} else {
System.err.println(String.format("%s -> %s at %d", prevState.name(), newState.name(),
TimeUtil.currentTimeMillis()));
}
});
}

private static void initDegradeRule() {
List<DegradeRule> rules = new ArrayList<DegradeRule>();
DegradeRule rule = new DegradeRule();
rule.setResource(KEY);
// set limit exception ratio to 0.1
rule.setCount(0.1);
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
rule.setTimeWindow(10);
rule.setMinRequestAmount(20);
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule(KEY)
.setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType())
// Set ratio threshold to 50%.
.setCount(0.5d)
.setStatIntervalMs(30000)
.setMinRequestAmount(50)
// Retry timeout (in second)
.setTimeWindow(10);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
System.out.println("Degrade rule loaded: " + rules);
}

private static void tick() {
private static void sleep(int timeMs) {
try {
TimeUnit.MILLISECONDS.sleep(timeMs);
} catch (InterruptedException e) {
// ignore
}
}

private static void startTick() {
Thread timer = new Thread(new TimerTask());
timer.setName("sentinel-timer-task");
timer.setName("sentinel-timer-tick-task");
timer.start();
}

@@ -130,16 +134,16 @@ public class ExceptionRatioDegradeDemo {
@Override
public void run() {
long start = System.currentTimeMillis();
System.out.println("begin to statistic!!!");
System.out.println("Begin to run! Go go go!");
System.out.println("See corresponding metrics.log for accurate statistic data");

long oldTotal = 0;
long oldPass = 0;
long oldBlock = 0;
long oldBizException = 0;
while (!stop) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
}
sleep(1000);

long globalTotal = total.get();
long oneSecondTotal = globalTotal - oldTotal;
oldTotal = globalTotal;
@@ -166,7 +170,7 @@ public class ExceptionRatioDegradeDemo {
}
long cost = System.currentTimeMillis() - start;
System.out.println("time cost: " + cost + " ms");
System.out.println("total:" + total.get() + ", pass:" + pass.get()
System.out.println("total: " + total.get() + ", pass:" + pass.get()
+ ", block:" + block.get() + ", bizException:" + bizException.get());
System.exit(0);
}

sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/degrade/RtDegradeDemo.java → sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/degrade/SlowRatioCircuitBreakerDemo.java Bestand weergeven

@@ -17,47 +17,28 @@ package com.alibaba.csp.sentinel.demo.degrade;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import com.alibaba.csp.sentinel.util.TimeUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreaker.State;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreakerStrategy;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
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.slots.block.degrade.circuitbreaker.EventObserverRegistry;
import com.alibaba.csp.sentinel.util.TimeUtil;

/**
* <p>
* Degrade is used when the resources are in an unstable state, these resources
* will be degraded within the next defined time window. There are two ways to
* measure whether a resource is stable or not:
* <ul>
* <li>
* Average Response Time ('DegradeRule.Grade=RuleContants.DEGRADE_GRADE_RT'): When the
* average RT greats than or equals to the threshold ('count' in 'DegradeRule', ms), the
* resource enters a quasi-degraded state. If the RT of next coming five requests still
* exceed this threshold, this resource will be downgraded, which means that in
* the next time window(Defined in 'timeWindow', s units) all the access to this
* resource will be blocked.
* </li>
* <li>
* Exception ratio, see {@link ExceptionRatioDegradeDemo}.
* </li>
* <li>
* Exception Count, see {@link ExceptionCountDegradeDemo}.
* </li>
* </ul>
*
* </p>
*
* Run this demo, and the out put will be like:
* Run this demo, and the output will be like:
*
* <pre>
* 1529399827825,total:0, pass:0, block:0
* 1529399828825,total:4263, pass:100, block:4164
* 1529399829825,total:19179, pass:4, block:19176
* 1529399830824,total:19806, pass:0, block:19806 //begin degrade
* 1529399829825,total:19179, pass:4, block:19176 // circuit breaker opens
* 1529399830824,total:19806, pass:0, block:19806
* 1529399831825,total:19198, pass:0, block:19198
* 1529399832824,total:19481, pass:0, block:19481
* 1529399833826,total:19241, pass:0, block:19241
@@ -66,95 +47,114 @@ import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
* 1529399836826,total:19490, pass:0, block:19492
* 1529399837828,total:19355, pass:0, block:19355
* 1529399838827,total:11388, pass:0, block:11388
* 1529399839829,total:14494, pass:104, block:14390 //After 10 seconds, the system is restored, and degraded very
* quickly
* 1529399839829,total:14494, pass:104, block:14390 // After 10 seconds, the system restored
* 1529399840854,total:18505, pass:0, block:18505
* 1529399841854,total:19673, pass:0, block:19676
* </pre>
*
* @author jialiang.linjl
* @author Eric Zhao
*/
public class RtDegradeDemo {
public class SlowRatioCircuitBreakerDemo {

private static final String KEY = "abc";
private static final String KEY = "some_method";

private static volatile boolean stop = false;
private static int seconds = 120;

private static AtomicInteger total = new AtomicInteger();
private static AtomicInteger pass = new AtomicInteger();
private static AtomicInteger block = new AtomicInteger();
private static AtomicInteger total = new AtomicInteger();

private static volatile boolean stop = false;
private static final int threadCount = 100;
private static int seconds = 60 + 40;

public static void main(String[] args) throws Exception {

tick();
initDegradeRule();

for (int i = 0; i < threadCount; i++) {
Thread entryThread = new Thread(new Runnable() {

@Override
public void run() {
while (true) {
Entry entry = null;
try {
TimeUnit.MILLISECONDS.sleep(5);
entry = SphU.entry(KEY);
// token acquired
pass.incrementAndGet();
// sleep 600 ms, as rt
TimeUnit.MILLISECONDS.sleep(600);
} catch (Exception e) {
block.incrementAndGet();
} finally {
total.incrementAndGet();
if (entry != null) {
entry.exit();
}
registerStateChangeObserver();
startTick();

int concurrency = 8;
for (int i = 0; i < concurrency; i++) {
Thread entryThread = new Thread(() -> {
while (true) {
Entry entry = null;
try {
entry = SphU.entry(KEY);
pass.incrementAndGet();
// RT: [40ms, 60ms)
sleep(ThreadLocalRandom.current().nextInt(40, 60));
} catch (BlockException e) {
block.incrementAndGet();
sleep(ThreadLocalRandom.current().nextInt(5, 10));
} finally {
total.incrementAndGet();
if (entry != null) {
entry.exit();
}
}
}

});
entryThread.setName("working-thread");
entryThread.setName("sentinel-simulate-traffic-task-" + i);
entryThread.start();
}
}

private static void registerStateChangeObserver() {
EventObserverRegistry.getInstance().addStateChangeObserver("logging",
(prevState, newState, rule, snapshotValue) -> {
if (newState == State.OPEN) {
System.err.println(String.format("%s -> OPEN at %d, snapshotValue=%.2f", prevState.name(),
TimeUtil.currentTimeMillis(), snapshotValue));
} else {
System.err.println(String.format("%s -> %s at %d", prevState.name(), newState.name(),
TimeUtil.currentTimeMillis()));
}
});
}

private static void initDegradeRule() {
List<DegradeRule> rules = new ArrayList<DegradeRule>();
DegradeRule rule = new DegradeRule();
rule.setResource(KEY);
// set threshold rt, 10 ms
rule.setCount(10);
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
rule.setTimeWindow(10);
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule(KEY)
.setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType())
// Max allowed response time
.setCount(50)
// Retry timeout (in second)
.setTimeWindow(10)
// Circuit breaker opens when slow request ratio > 60%
.setSlowRatioThreshold(0.6)
.setMinRequestAmount(100)
.setStatIntervalMs(20000);
rules.add(rule);

DegradeRuleManager.loadRules(rules);
System.out.println("Degrade rule loaded: " + rules);
}

private static void sleep(int timeMs) {
try {
TimeUnit.MILLISECONDS.sleep(timeMs);
} catch (InterruptedException e) {
// ignore
}
}

private static void tick() {
private static void startTick() {
Thread timer = new Thread(new TimerTask());
timer.setName("sentinel-timer-task");
timer.setName("sentinel-timer-tick-task");
timer.start();
}

static class TimerTask implements Runnable {

@Override
public void run() {
long start = System.currentTimeMillis();
System.out.println("begin to statistic!!!");
System.out.println("Begin to run! Go go go!");
System.out.println("See corresponding metrics.log for accurate statistic data");

long oldTotal = 0;
long oldPass = 0;
long oldBlock = 0;

while (!stop) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
}
sleep(1000);

long globalTotal = total.get();
long oneSecondTotal = globalTotal - oldTotal;
@@ -178,10 +178,9 @@ public class RtDegradeDemo {

long cost = System.currentTimeMillis() - start;
System.out.println("time cost: " + cost + " ms");
System.out.println("total:" + total.get() + ", pass:" + pass.get()
System.out.println("total: " + total.get() + ", pass:" + pass.get()
+ ", block:" + block.get());
System.exit(0);
}
}

}

Laden…
Annuleren
Opslaan