0
点赞
收藏
分享

微信扫一扫

SpringCloud原理--hystrix的熔断


简介

        本文介绍SpringCloud的hystrix的断路器的原理。

        本内容也是Java后端面试常见的问题。

原理

        断路器是如何决策熔断和记录信息的呢?

        看断路器HystrixCircuitBreaker的定义:

public interface HystrixCircuitBreaker {
public static class Factory {...}
static class HystrixCircuitBreakerlmpl implements HystrixCircuitBreaker {… }
static class NoOpCircuitBreaker implements HystrixCircuitBreaker {… }
public boolean allowRequest();
public boolean isOpen();
void markSuccess() ;
}

可以看到它的接口定义并不复杂,主要定义了三个断路器的抽象方法。


  • allowRequest():每个Hystrix命令的请求都通过它判断是否被执行。
  • isOpen():返回当前断路器是否打开。
  • markSuccess():用来闭合断路器。

另外还有三个静态类。


  1. 静态类Factory中维护了一个Hystrix命令与HystrixCircuitBreaker的关系集合:ConcurrentHashMap<String,HystrixCircuitBreaker>cpircuitBreakersByCommand,其中String类型的key通过HystrixCommandKey定义,每一个Hystrix命令需要有一个key来标识,同时一个Hystrix命令也会在该集合中找到它对应的断路器HystrixCircuitBreaker实例。
  2. 静态类NoOpCircuitBreaker定义了一个什么都不做的断路器实现,它允许所有请求,并且断路器状态始终闭合。
  3. 静态类HystrixCircuitBreakerlmpl是断路器接口HystrixCircuitBreaker的实现类,在该类中定义了断路器的4个核心对象。

  1. HystrixCommandPropertiesproperties:断路器对应HystrixCommand实例的属性对象,它的详细内容我们将在后续章节做具体的介绍。 
  2. HystrixCommandMetricsmetrics:用来让HystrixCommand记录各类度量指标的对象。
  3. AtomicBooleancircuitOpen:断路器是否打开的标志,默认为false。
  4. AtomicLongcircuitOpenedOrLastTestedTime:断路器打开或是上一次测试的时间戳。


HystrixCircuitBreakerlmpl对HystrixCircuitBreaker接口的各个方法实现如下所示。

isOpen()

判断断路器的打开/关闭状态。


  • 如果断路器打开标识为true,则直接返回true,表示断路器处于打开状态。否则,就从度量指标对象metrics中获取HealthCounts统计对象做进一步判断(该对象记录了一个滚动时间窗内的请求信息快照,默认时间窗为10秒)。如果它的请求总数(QPS)在预设的阈值范围内就返回false,表示断路器处于未打开状态。该阈值的配置参数为circuitBreakerRequestVolumeThreshold,默认值为20。
  • 如果错误百分比在阈值范围内就返回false,表示断路器处于未打开状态。该阈值的配置参数为circuitBreakerErrorThresholdPercentage,默认值为50。
  • 如果上面的两个条件都不满足,则将断路器设置为打开状态(熔断/短路)。同时,如果是从关闭状态切换到打开状态的话,就将当前时间记录到上面提到的circuitOpenedOrLastTestedTime对象中。

isOpen()源码 

public boolean isOpen() {
if (circuitOpen.get()) {
return true;
HealthCounts health = metrics.getHealthCounts ();
if (health.getTotalRequests() {}
properties.circuitBreakerRequestVolumeThreshold().get()) {
return false;
}
if (health.getErrorPercentage() {
properties.circuitBreakerErrorThresholdPercentage().get()) {
return false;
} else {
if (circuitOpen.compareAndSet(false, true)) {
circuitOpenedOrLastTestedTime.set(System.currentTimeMillis());
return true;
} else {
return true;
}
}
}

allowRequest()

        作用:判断请求是否被允许。

        先根据配置对象properties中的断路器判断强制打开或关闭属性是否被设置。如果强制打开,就直接返回false,拒绝请求。如果强制关闭,它会允许所有请求,但是同时也会调用

isOpen()来执行断路器的计算逻辑,用来模拟断路器打开/关闭的行为。在默认情况下,断路器并不会进入这两个强制打开或关闭的分支中去,而是通过!isOpen()||allowSingleTest()来判断是否允许请求访问。!isOpen()之前已经介绍过,用来判断和计算当前断路器是否打开,如果是关闭状态就允许请求。

allowRequest()源码

@Override
public boolean allowRequest() {
if (properties.circuitBreakerForceOpen().get()) {
return false;
}
if (properties.circuitBreakerForceClosedO .get()) {
isOpen ();
return true;
}
return !isOpen( ) || allowSingleTest();
}

那么allowSingleTest()是用来做什么的呢?

public boolean allowSingleTest () {
long timeCircuitOpenedOrWasLastTested = circuitOpenedOrLastTestedTime.get();
if (circuitOpen.get() && System.currentTimeMillis())
timeCircuitOpenedOrWasLastTested + properties.circuitBreakerSleepWindowInMilliseconds{).get ()) {
if (circuitOpenedOrLastTestedTime.compareAndSet(
timeCircuitOpenedOrWasLastTested, System.currentTimeMillis())) {
return true;
}
}
return false;
}

        从allowSingleTest()的实现中我们可以看到,这里使用了在isOpen()函数中当断路器从闭合到打开时候所记录的时间戳。当断路器在打开状态的时候,这里会判断断开时的时间戳+配置中的circuitBreakerSleepWindowInMilliseconds时间是否小于当前时间,是的话,就将当前时间更新到记录断路器打开的时间对象circuitOpenedOrLastTestedTime中,并且允许此次请求。简单地说,通过circuitBreakerSleepWindowInMilliseconds属性设置了一个断路器打开之后的休眠时间(默认为5秒),在该休眠时间到达之后,将再次允许请求尝试访问,此时断路器处于“半开”状态,若此时请求继续失败,断路器又进入打开状态,并继续等待下一个休眠窗口过去之后再次尝试;若请求成功,则将断路器重新置于关闭状态。所以通过allowSingleTest()与isOpen()方法的配合,实现了断路器打开和关闭状态的切换。

markSuccess()

该函数在“半开路”状态时使用。

若 Hystrix命令调用成功,通过调用它将打开的断路器关闭,并重置度量指标对象。

public void markSuccess() {
if (circuitOpen.get()) {
if (circuitOpen.compareAndSet(true, false)) {
metrics.resetStream();
}
}
}

 其他网址

《SpringCloud微服务实战》

        => 第5章 服务容错保护:Spring Cloud Hystrix

                => 原理分析

                        => 断路器原理

《深入理解Spring Cloud与微服务构建》

        => 8.4  Hystrix的工作机制


举报

相关推荐

0 条评论