【Java】hystrix - hystrix怎么知道他已经熔断了

hystrix - hystrix怎么知道他已经熔断了

大军发布于 今天 15:55

hystrix - Fallback是怎么调用的提到了allowRequest方法,我们看看这里是做了哪些。

public boolean allowRequest() {

// 配置了强制熔断,直接返回false

if (properties.circuitBreakerForceOpen().get()) {

// properties have asked us to force the circuit open so we will allow NO requests

return false;

}

// 强制关闭

if (properties.circuitBreakerForceClosed().get()) {

// we still want to allow isOpen() to perform it's calculations so we simulate normal behavior

isOpen();

// properties have asked us to ignore errors so we will ignore the results of isOpen and just allow all traffic through

return true;

}

return !isOpen() || allowSingleTest();

}

public boolean isOpen() {

// 获取熔断器的状态,true就是开

if (circuitOpen.get()) {

// 如果是开的,还是返回ture,留给半开的时候用

return true;

}

// 如果是关的,获取HealthCounts信息

HealthCounts health = metrics.getHealthCounts();

// 当前的请求数如果小于设置的阈值,就直接返回false,说明没开

// 比如我们设置了20,此时才19,也是没有开的

// 这个值是样品数量的值,只有足够数量的样品,才比较准确

if (health.getTotalRequests() < properties.circuitBreakerRequestVolumeThreshold().get()) {

// we are not past the minimum volume threshold for the statisticalWindow so we'll return false immediately and not calculate anything

return false;

}

// 错误比例小于设定的值,比如错误的比例超过50%,就开启熔断

if (health.getErrorPercentage() < properties.circuitBreakerErrorThresholdPercentage().get()) {

return false;

} else {

// 这边设置时间,用于半开状态

if (circuitOpen.compareAndSet(false, true)) {

// if the previousValue was false then we want to set the currentTime

circuitOpenedOrLastTestedTime.set(System.currentTimeMillis());

return true;

} else {

// How could previousValue be true? If another thread was going through this code at the same time a race-condition could have

// caused another thread to set it to true already even though we were in the process of doing the same

// In this case, we know the circuit is open, so let the other thread set the currentTime and report back that the circuit is open

return true;

}

}

}

流程图如下:【Java】hystrix - hystrix怎么知道他已经熔断了

半开状态

上面还有一个方法,allowSingleTest。这个是用于处理半开的时候。
我们上面知道,当熔断的时候,会保存一个值,circuitOpenedOrLastTestedTime。这个值加上设置的休眠时间和当前时间做比较,看看能不能允许尝试访问一次。

public boolean allowSingleTest() {

long timeCircuitOpenedOrWasLastTested = circuitOpenedOrLastTestedTime.get();

// 熔断器开的时候,并且当前时间>熔断时间+休眠时间

// 也就是说休眠时间设置为5,那5秒后给他一个机会看看能不能访问,也就是半开状态

// 然后重新设置circuitOpenedOrLastTestedTime

if (circuitOpen.get() && System.currentTimeMillis() > timeCircuitOpenedOrWasLastTested + properties.circuitBreakerSleepWindowInMilliseconds().get()) {

if (circuitOpenedOrLastTestedTime.compareAndSet(timeCircuitOpenedOrWasLastTested, System.currentTimeMillis())) {

return true;

}

}

return false;

}

HystrixCircuitBreaker创建

allowRequest是HystrixCircuitBreaker的方法,我们稍微回顾一下command的创建,AbstractCommand中,会调用initCircuitBreaker方法。他会通过HystrixCircuitBreaker的Factory来创建的

private static HystrixCircuitBreaker initCircuitBreaker(boolean enabled, HystrixCircuitBreaker fromConstructor,

HystrixCommandGroupKey groupKey, HystrixCommandKey commandKey,

HystrixCommandProperties properties, HystrixCommandMetrics metrics) {

if (enabled) {

if (fromConstructor == null) {

// get the default implementation of HystrixCircuitBreaker

return HystrixCircuitBreaker.Factory.getInstance(commandKey, groupKey, properties, metrics);

} else {

return fromConstructor;

}

} else {

return new NoOpCircuitBreaker();

}

}

在工厂中,他其实会通过缓存来获取的,也就是说每个CommandKey都有对应的HystrixCircuitBreaker。如果缓存没有,则创建一个放入缓存。

public static HystrixCircuitBreaker getInstance(HystrixCommandKey key, HystrixCommandGroupKey group, HystrixCommandProperties properties, HystrixCommandMetrics metrics) {

// 从circuitBreakersByCommand缓存里取,key是CommandKey

HystrixCircuitBreaker previouslyCached = circuitBreakersByCommand.get(key.name());

if (previouslyCached != null) {

return previouslyCached;

}

// 缓存没有,创建一个放入缓存中

HystrixCircuitBreaker cbForCommand = circuitBreakersByCommand.putIfAbsent(key.name(), new HystrixCircuitBreakerImpl(key, group, properties, metrics));

if (cbForCommand == null) {

// this means the putIfAbsent step just created a new one so let's retrieve and return it

return circuitBreakersByCommand.get(key.name());

} else {

// this means a race occurred and while attempting to 'put' another one got there before

// and we instead retrieved it and will now return it

return cbForCommand;

}

}

java源码分析hystrix

阅读 64发布于 今天 15:55

本作品系原创,采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议

avatar

大军

运气好的时候要拼命努力,运气不好的时候要储备能力

370 声望

29 粉丝

0 条评论

得票时间

avatar

大军

运气好的时候要拼命努力,运气不好的时候要储备能力

370 声望

29 粉丝

宣传栏

hystrix - Fallback是怎么调用的提到了allowRequest方法,我们看看这里是做了哪些。

public boolean allowRequest() {

// 配置了强制熔断,直接返回false

if (properties.circuitBreakerForceOpen().get()) {

// properties have asked us to force the circuit open so we will allow NO requests

return false;

}

// 强制关闭

if (properties.circuitBreakerForceClosed().get()) {

// we still want to allow isOpen() to perform it's calculations so we simulate normal behavior

isOpen();

// properties have asked us to ignore errors so we will ignore the results of isOpen and just allow all traffic through

return true;

}

return !isOpen() || allowSingleTest();

}

public boolean isOpen() {

// 获取熔断器的状态,true就是开

if (circuitOpen.get()) {

// 如果是开的,还是返回ture,留给半开的时候用

return true;

}

// 如果是关的,获取HealthCounts信息

HealthCounts health = metrics.getHealthCounts();

// 当前的请求数如果小于设置的阈值,就直接返回false,说明没开

// 比如我们设置了20,此时才19,也是没有开的

// 这个值是样品数量的值,只有足够数量的样品,才比较准确

if (health.getTotalRequests() < properties.circuitBreakerRequestVolumeThreshold().get()) {

// we are not past the minimum volume threshold for the statisticalWindow so we'll return false immediately and not calculate anything

return false;

}

// 错误比例小于设定的值,比如错误的比例超过50%,就开启熔断

if (health.getErrorPercentage() < properties.circuitBreakerErrorThresholdPercentage().get()) {

return false;

} else {

// 这边设置时间,用于半开状态

if (circuitOpen.compareAndSet(false, true)) {

// if the previousValue was false then we want to set the currentTime

circuitOpenedOrLastTestedTime.set(System.currentTimeMillis());

return true;

} else {

// How could previousValue be true? If another thread was going through this code at the same time a race-condition could have

// caused another thread to set it to true already even though we were in the process of doing the same

// In this case, we know the circuit is open, so let the other thread set the currentTime and report back that the circuit is open

return true;

}

}

}

流程图如下:【Java】hystrix - hystrix怎么知道他已经熔断了

半开状态

上面还有一个方法,allowSingleTest。这个是用于处理半开的时候。
我们上面知道,当熔断的时候,会保存一个值,circuitOpenedOrLastTestedTime。这个值加上设置的休眠时间和当前时间做比较,看看能不能允许尝试访问一次。

public boolean allowSingleTest() {

long timeCircuitOpenedOrWasLastTested = circuitOpenedOrLastTestedTime.get();

// 熔断器开的时候,并且当前时间>熔断时间+休眠时间

// 也就是说休眠时间设置为5,那5秒后给他一个机会看看能不能访问,也就是半开状态

// 然后重新设置circuitOpenedOrLastTestedTime

if (circuitOpen.get() && System.currentTimeMillis() > timeCircuitOpenedOrWasLastTested + properties.circuitBreakerSleepWindowInMilliseconds().get()) {

if (circuitOpenedOrLastTestedTime.compareAndSet(timeCircuitOpenedOrWasLastTested, System.currentTimeMillis())) {

return true;

}

}

return false;

}

HystrixCircuitBreaker创建

allowRequest是HystrixCircuitBreaker的方法,我们稍微回顾一下command的创建,AbstractCommand中,会调用initCircuitBreaker方法。他会通过HystrixCircuitBreaker的Factory来创建的

private static HystrixCircuitBreaker initCircuitBreaker(boolean enabled, HystrixCircuitBreaker fromConstructor,

HystrixCommandGroupKey groupKey, HystrixCommandKey commandKey,

HystrixCommandProperties properties, HystrixCommandMetrics metrics) {

if (enabled) {

if (fromConstructor == null) {

// get the default implementation of HystrixCircuitBreaker

return HystrixCircuitBreaker.Factory.getInstance(commandKey, groupKey, properties, metrics);

} else {

return fromConstructor;

}

} else {

return new NoOpCircuitBreaker();

}

}

在工厂中,他其实会通过缓存来获取的,也就是说每个CommandKey都有对应的HystrixCircuitBreaker。如果缓存没有,则创建一个放入缓存。

public static HystrixCircuitBreaker getInstance(HystrixCommandKey key, HystrixCommandGroupKey group, HystrixCommandProperties properties, HystrixCommandMetrics metrics) {

// 从circuitBreakersByCommand缓存里取,key是CommandKey

HystrixCircuitBreaker previouslyCached = circuitBreakersByCommand.get(key.name());

if (previouslyCached != null) {

return previouslyCached;

}

// 缓存没有,创建一个放入缓存中

HystrixCircuitBreaker cbForCommand = circuitBreakersByCommand.putIfAbsent(key.name(), new HystrixCircuitBreakerImpl(key, group, properties, metrics));

if (cbForCommand == null) {

// this means the putIfAbsent step just created a new one so let's retrieve and return it

return circuitBreakersByCommand.get(key.name());

} else {

// this means a race occurred and while attempting to 'put' another one got there before

// and we instead retrieved it and will now return it

return cbForCommand;

}

}

以上是 【Java】hystrix - hystrix怎么知道他已经熔断了 的全部内容, 来源链接: utcz.com/a/108071.html

回到顶部