熔断降级是指当资源处于不稳定的情况下,在接下来的时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出DegradeException)。
通常用三种方式来衡量资源是否处于稳定的状态:
-
平均响应时间 (DEGRADE_GRADE_RT):当资源的平均响应时间超过阈值(DegradeRule 中的 count,以 ms 为单位)之后,资源进入准降级状态。接下来如果持续进入 5 个请求,它们的 RT 都持续超过这个阈值,那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回(抛出 DegradeException)。
-
异常比例 (DEGRADE_GRADE_EXCEPTION_RATIO):当资源的每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
-
异常数 (DEGRADE_GRADE_EXCEPTION_COUNT):当资源近 1 分钟的异常数目超过阈值之后会进行熔断。
注意:为了统计异常比例或异常数,需要通过 Tracer.trace(ex) 记录业务异常。
下面对这三种情况做简单的验证
- 导入Maven依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.3.0-GA</version>
</dependency>
点击这里可查询最新的sentinel-core版本
1、验证平均响应时间
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.util.TimeUtil;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 降级是在资源处于不稳定状态时使用的,这些资源将在下一个定义的时间窗口内降级。
* 有三种方法衡量资源是否稳定:
* 平均响应时间 (DEGRADE_GRADE_RT):当资源的平均响应时间超过阈值(DegradeRule 中的 count,以 ms 为单位)之后,
* 资源进入准降级状态。接下来如果持续进入 5 个请求,它们的 RT 都持续超过这个阈值,
* 那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,
* 对这个方法的调用都会自动地返回(抛出 DegradeException)
* **异常比率,见 {@link ExceptionRatioDegradeDemo}.
* **异常统计,见 {@link ExceptionCountDegradeDemo}.
*/
public class RtDegradeDemo {
private static final String KEY = "平均响应时间";
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;
public static void main(String[] args) throws Exception {
tick();
initDegradeRule();// 设置资源降级规则
for (int i = 0; i < threadCount; i++) {
Thread entryThread = new Thread(new Runnable() {
int j = 0;
@Override
public void run() {
while (true) {
Entry entry = null;
try {
TimeUnit.MILLISECONDS.sleep(5);
entry = SphU.entry(KEY);
// 令牌已获得
pass.incrementAndGet();// 先+1,然后在返回值,相当于++i
// sleep 600 ms, as rt
TimeUnit.MILLISECONDS.sleep(600);
} catch (Exception e) {
// System.out.println("异常:"+e);
// 降级计数
block.incrementAndGet();// 先+1,然后在返回值,相当于++i
} finally {
// 记录总数
total.incrementAndGet();// 先+1,然后在返回值,相当于++i
if (entry != null) {
entry.exit();
}
}
}
}
});
entryThread.setName("working-thread");
entryThread.start();
}
}
/**
* 当资源的平均响应时间超过阈值(DegradeRule 中的 count,以 ms 为单位)之后,资源进入准降级状态。
* 接下来如果持续进入 5 个请求,它们的 RT 都持续超过这个阈值,
* 那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,
* 对这个方法的调用都会自动地返回(抛出 DegradeException)。
*/
private static void initDegradeRule() {
List<DegradeRule> rules = new ArrayList<DegradeRule>();
DegradeRule rule = new DegradeRule();
rule.setResource(KEY);// 设置资源名,资源名是限流规则的作用对象
rule.setCount(10);// 设置平均响应时间阈值为10ms
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);// 设置降级模式,根据平均响应时间降级
rule.setTimeWindow(10);// 设置降级的时间,以s为单位
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("统计开始......");
long oldTotal = 0;
long oldPass = 0;
long oldBlock = 0;
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String nowTime = "";
while (!stop) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
}
long globalTotal