目录
8. 断路器功能
8.1 定义
从类图来看,断路器主要有三个方法,而默认的实现类多一个方法,我们看下这四个方法的作用
allowRequest
: 判断断路器是否放行
isOpen()
: 判断断路器是否开启
allowSingleTest()
: 是否可以半打开,即在断路器打开的状态下允许放行单次请求
markSuccess()
: 半打开状态->关闭
接下来通过源码继续分析
// HystrixCircuitBreakerImpl
public void markSuccess() {
// 判断断路器是否开启,即半打开
if (circuitOpen.get()) {
// 如果开启则将其关闭
if (circuitOpen.compareAndSet(true, false)) {
// 重置统计信息
metrics.resetStream();
}
}
}
@Override
public boolean allowRequest() {
if (properties.circuitBreakerForceOpen().get()) {
// 断路器设置了强制打开,直接返回false
return false;
}
if (properties.circuitBreakerForceClosed().get()) {
// 断路器设置了强制关闭, 但依旧进行信息统计
isOpen();
return true;
}
// 1) 断路器关闭,直接放行
// 2) 断路器开启,查看是否达到半打开的条件,达到则放行本次请求;不达到则拦截
return !isOpen() || allowSingleTest();
}
public boolean allowSingleTest() {
long timeCircuitOpenedOrWasLastTested = circuitOpenedOrLastTestedTime.get();
// 1) 如果断路器开启
// 2) 并且开启时间已经超过设置的休眠时间(circuitBreaker.sleepWindowInMilliseconds)
if (circuitOpen.get() && System.currentTimeMillis() > timeCircuitOpenedOrWasLastTested + properties.circuitBreakerSleepWindowInMilliseconds().get()) {
// 设置当前时间为断路器开启时间
if (circuitOpenedOrLastTestedTime.compareAndSet(timeCircuitOpenedOrWasLastTested, System.currentTimeMillis())) {
// 半打开状态,允许本次请求通行
return true;
}
}
return false;
}
@Override
public boolean isOpen() {
if (circuitOpen.get()) {
return true;
}
// 统计信息metrics请看第10节
HealthCounts health = metrics.getHealthCounts();
// 判断时间窗口内的请求数是否小于circuitBreaker.requestVolumeThreshold(可通过@HystrixProperty设置)
if (health.getTotalRequests() < properties.circuitBreakerRequestVolumeThreshold().get()) {
// 小于则返回false,断路器不开启
return false;
}
// 判断失败比例是否小于参数circuitBreaker.errorThresholdPercentage(可通过@HystrixProperty设置)
if (health.getErrorPercentage() < properties.circuitBreakerErrorThresholdPercentage().get()) {
// 小于则表明当前请求正常,断路器关闭
return false;
} else {
// 滚动窗口内失败比例过高,则将断路器打开
if (circuitOpen.compareAndSet(false, true)) {
// 设置断路器打开时间
circuitOpenedOrLastTestedTime.set(System.currentTimeMillis());
return true;
} else {
// 多线程情况,另一线程已经做了处理
return true;
}
}
}
8.2 参数设置
关于断路器的参数
@HystrixCommand(commandProperties = {
// 是否开启断路器功能,默认true
@HystrixProperty(name = "circuitBreaker.enabled"