Hystrix 的熔断
熔断断路器的重要功能之一,是实现快速失败的基础;
Hystrix的熔断器设计成一个接口 com.netflix.hystrix.HystrixCircuitBreaker,解释如下:
/** * Circuit-breaker logic that is hooked into {@link HystrixCommand} execution and will stop allowing executions if failures have gone past the defined threshold. * <p> * It will then allow single retries after a defined sleepWindow until the execution succeeds at which point it will again close the circuit and allow executions again. */
大意就是,在失败请求达到一定量时终止执行HystrixCommand,并且允许一定时间(sleepWindow)后重试一次,成功后就关掉断路器;
熔断主要涉及到三个方面的问题:
1、如何实现熔断,如何恢复
2、怎么判断是否该熔断
3、判断熔断的基础指标数据如何收集和统计
上面就已经大致解释了第一个问题;
下面就主要围绕这三个问题进行解释。
一、如何熔断
断路器中熔断与恢复一般设计成一个开关,使用一个布尔值来实现
/* track whether this circuit is open/closed at any given point in time (default to false==closed) */ private AtomicBoolean circuitOpen = new AtomicBoolean(false);
当请求失败达到熔断阈值(threshold)时,断路器就会打开,请求就会快速失败;
当断路器打开一段时间后(sleepWindow)后,组件会使用一个请求去重试,看看链路是否恢复,如果恢复就关闭断路器,接下来的请求就会发送到依赖的服务上;
二、怎么判断是否该熔断
Hystrix 在一个滑动窗口时间内,统计出各种状态的请求数量和比例(failure + success + timeout + threadPoolRejected + semaphoreRejected), 就是下面的HealthCounts;
HealthCounts health = metrics.getHealthCounts(); if (health.getTotalRequests() < properties.circuitBreakerRequestVolumeThreshold().get()) { return false; } if (health.getErrorPercentage() < properties.circuitBreakerErrorThresholdPercentage().get()) { return false; } else { // our failure rate is too high, trip the circuit if (circuitOpen.compareAndSet(false, true)) {circuitOpenedOrLastTestedTime.set(System.currentTimeMillis()); return true; } else { return true; } }
判断是否打开有两种方式:一种是设置一个阈值,一种是设置一个失败比例;
三、如何收集和统计指标数据
由第二部分内容我们知道HealthCounts 的数据来源于metrics(指标),那么指标是如何收集和统计的呢?
熔断统计就会涉及到两个基本信息:总共统计数据和单位时间(rolling window)统计数据;注:rolling window is defined by HystrixCommandProperties#metricsRollingStatisticalWindowInMilliseconds()
收集时将hystrix的命令调用抽象了事件流,利用响应式编程技术将事件汇总;
统计时使用RxJava的window/reduce/flatmap等命令将单位事件内的数据进行汇总存储(桶),再将桶内的数据按成功/失败的进行统计;
统计的数据就是metrics(指标)数据;
网上看到一片写得不错的文章:
并附上该作者画的总体流程图: