一、服务熔断和服务降级
服务熔断:应对雪崩效应的链路自我保护机制,只有在一定时间内服务调用失败(报错、超时、宕机)达到一定次数,才会启动服务熔断,后面的请求直接走服务降级的处理方法,服务熔断会自动断开并且自动恢复。
服务降级:当服务调用出现响应时间过长或者运行出错或者宕机,就会调用服务降级方法快速响应,即直接返回一个提前准备好的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 状态 (熔断关闭),熔断关闭不会对服务进行熔断。
四、断路器开启或关闭的条件
-
当请求次数满足一定的阀值的时候,默认10秒内超过20个请求次数。
-
当失败率达到一定的时候,默认10秒内超过50%请求失败。
-
到达以上阀值,断路器将会开启。
-
当开启的时候(即熔断打开),所有请求都不会进行转发,直接走服务降级的逻辑。
-
一段时间之后,(默认5秒,所以说这5秒处于服务熔断状态),这个时候断路器是半开状态,会让其中一个请求进行转发,如果成功,断路器会关闭,若失败,继续开启,重复4,5。
五、断路器起作用的场景
涉及到三个重要参数,快照时间窗口,请求总数阈值,错误百分比阈值
-
快照时间窗
断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒
-
请求总数阀值
在快照时间窗内,必须满足请求总数阀值才有资格熔断。默认20秒。意味着在10秒内,如果该hystrix命令的调用次数不足20次,即使所有请求都超时或其他原因失败,断路器都不会打开
-
错误百分比阀值
当请求总数在快照时间窗内超过了阀值,比如发生了30次调用,如果在这30次调用中,有15次发生了超时异常,也就是超过了50%的错误百分比,在默认设定50%阀值情况下,这时候就会将断路器打开
六、Hystrix 工作流程
讲解一下工作流程(按照默认参数讲解)
-
当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)