Hystrix熔断器

458 阅读6分钟

一、服务熔断和服务降级

服务熔断:应对雪崩效应的链路自我保护机制,只有在一定时间内服务调用失败(报错、超时、宕机)达到一定次数,才会启动服务熔断,后面的请求直接走服务降级的处理方法,服务熔断会自动断开并且自动恢复。

服务降级:当服务调用出现响应时间过长或者运行出错或者宕机,就会调用服务降级方法快速响应,即直接返回一个提前准备好的fallback(退路)错误处理信息。

值得注意的是,服务熔断和服务降级一般都是同时发生的,当启动服务熔断之后,后续请求直接走服务降级的fallback方法,如果不启动服务熔断呢,假设是第一次请求进来,然后服务A宕机了,这时调用不成功,走服务降级的fallback方法,值得注意的是,是先调用原有的方法,不成功,再走降级方法,当不成功的次数达到一定上限时,启动服务熔断后,后续请求是直接走fallback降级方法,这就是两者的区别。

二、Hystrix 舱壁模式(线程池隔离策略)

默认 Hystrix 有一个线程池,数量为10个,为所有添加 @HystrixCommand 注解的方法提供线程,注意的是,这里是针对加了注解的所有方法,如果这些方法接收的请求超过10个,其他请求就得等待或者拒绝连接。

举个例子:如果所有熔断方法都使用 Hystrix 默认的线程池,为10个,假设我有方法A和方法B都加了 @HystrixCommand 注解,如果方法A接收的请求大于10个,把10个线程都用完了,接下来请求方法B,方法B根本处理不了,因为没有线程可以用,但这并不代表方法B这个服务是不可用的。

所以针对上述的情况,我们发现使用默认提供的线程池存在问题,下面 Hystrix 也提供线程池参数给我们自己配置来解决这个问题。

@HystrixCommand(threadPoolKey = "findResumeOpenStateTimeout")
public void methodA()
    
@HystrixCommand(threadPoolKey = "findResumeOpenStateTimeoutFallback")
public void methodB()

上述例子,方法A和方法B使用各自的线程池 findResumeOpenStateTimeout 和 findResumeOpenStateTimeoutFallback ,注意线程池标识保持唯一,这样子就不会共用线程池。

三、熔断类型

  • open 状态 (熔断打开),即请求直接走服务降级 fallback 方法,启动服务熔断。
  • half open 状态 (熔断半开),部分请求按照规则调用当前服务,当请求成功后则认为当前服务正常,关闭熔断。
  • closed 状态 (熔断关闭),熔断关闭不会对服务进行熔断。

四、断路器开启或关闭的条件

  1. 当请求次数满足一定的阀值的时候,默认10秒内超过20个请求次数。

  2. 当失败率达到一定的时候,默认10秒内超过50%请求失败。

  3. 到达以上阀值,断路器将会开启。

  4. 当开启的时候(即熔断打开),所有请求都不会进行转发,直接走服务降级的逻辑。

  5. 一段时间之后,(默认5秒,所以说这5秒处于服务熔断状态),这个时候断路器是半开状态,会让其中一个请求进行转发,如果成功,断路器会关闭,若失败,继续开启,重复4,5。

五、断路器起作用的场景

涉及到三个重要参数,快照时间窗口,请求总数阈值,错误百分比阈值

  • 快照时间窗

    断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒

  • 请求总数阀值

    在快照时间窗内,必须满足请求总数阀值才有资格熔断。默认20秒。意味着在10秒内,如果该hystrix命令的调用次数不足20次,即使所有请求都超时或其他原因失败,断路器都不会打开

  • 错误百分比阀值

    当请求总数在快照时间窗内超过了阀值,比如发生了30次调用,如果在这30次调用中,有15次发生了超时异常,也就是超过了50%的错误百分比,在默认设定50%阀值情况下,这时候就会将断路器打开

六、Hystrix 工作流程

滑动窗口.jpg 讲解一下工作流程(按照默认参数讲解)

  • 当10S之内达到最小请求20个,并且错误阈值达到50%,即20个请求中有10个出错,则开启服务熔断

  • 再有请求调用的时候,将不会调用主逻辑,而是直接调用降级fallback,通过断路器,实现了自动地发现错误并将降级逻辑切换为主逻辑,减少响应延迟的效果

  • 当断路器打开,对主逻辑进行熔断之后 ,hystrix会启动一个休眠窗口(默认5秒),在这个时间窗内,降级逻辑是临时的成为主逻辑

  • 当休眠时间窗口到期,断路器进入半开状态,释放一次请求到原来的主逻辑上,如果此次请求正常返回,那么断路器会进行关闭

  • 主逻辑恢复,如果这次请求依然有问题,断路器继续进入打开状态,休眠时间窗重新计时 上面流程举个详细配置的例子

/**
* 8秒钟内,请求次数达到2个,并且失败率在50%以上,就跳闸,跳闸后活动窗⼝设置为3s(跳闸后睡眠3秒,3秒之后,服务熔断开启变成服务半开的状态)
*/
@HystrixCommand(
	commandProperties = {
		@HystrixProperty(name ="metrics.rollingStats.timeInMilliseconds",value = "8000"),
		@HystrixProperty(name ="circuitBreaker.requestVolumeThreshold",value = "2"),
		@HystrixProperty(name ="circuitBreaker.errorThresholdPercentage",value = "50"),
		@HystrixProperty(name ="circuitBreaker.sleepWindowInMilliseconds",value = "3000")
})

七、Hystrix 常见配置参数

  • 断路器(Circuit Breaker) circuitBreaker.enabled

设置断路器是否起作用,一般配置在全局配置文件,不在单独方法上做配置。

默认值:true

默认属性:hystrix.command.default.circuitBreaker.enabled

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.enabled

实例默认的设置:HystrixCommandProperties.Setter().withCircuitBreakerEnabled(boolean value)

circuitBreaker.requestVolumeThreshold

设置在一个滚动窗口中,打开断路器需要达到的最少请求数。

比如:如果值是20,在一个窗口内(比如10秒),收到19个请求,即使这19个请求都失败了,断路器也不会打开。

默认值:20

默认属性:hystrix.command.default.circuitBreaker.requestVolumeThreshold

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.requestVolumeThreshold

实例默认的设置:HystrixCommandProperties.Setter().withCircuitBreakerRequestVolumeThreshold(int value)

circuitBreaker.sleepWindowInMilliseconds

设置在回路被打开,拒绝请求到再次尝试请求并决定回路是否继续打开的时间。

默认值:5000(毫秒)

默认属性:hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.sleepWindowInMilliseconds

实例默认的设置:

HystrixCommandProperties.Setter().withCircuitBreakerSleepWindowInMilliseconds(int value)

circuitBreaker.errorThresholdPercentage

设置打开回路并启动回退逻辑的错误阈值比率。

默认值:50

默认属性:hystrix.command.default.circuitBreaker.errorThresholdPercentage

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.errorThresholdPercentage

实例默认的设置:HystrixCommandProperties.Setter().withCircuitBreakerErrorThresholdPercentage(int value)

circuitBreaker.forceOpen

如果该属性设置为true,强制断路器进入打开状态,将会拒绝所有的请求。

该属性优先级比*circuitBreaker.forceClosed*高。

默认值:false

默认属性:hystrix.command.default.circuitBreaker.forceOpen

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.forceOpen

实例默认的设置:HystrixCommandProperties.Setter().withCircuitBreakerForceOpen(boolean value)

circuitBreaker.forceClosed

如果该属性设置为true,强制断路器进入关闭状态,将会允许所有的请求,无视错误率。

默认值:false

默认属性:hystrix.command.default.circuitBreaker.forceClosed

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.forceClosed

实例默认的设置:HystrixCommandProperties.Setter().withCircuitBreakerForceClosed(boolean value)