Java虚拟机:SpringCloud的限流、降级和熔断——Hystrix( 四 )


2、线程隔离-信号量
上面提到了线程池隔离的缺点 , 当依赖延迟极低的服务时 , 线程池隔离技术引入的开销超过了它所带来的好处 。 这时候可以使用信号量隔离技术来代替 , 通过设置信号量来限制对任何给定依赖的并发调用量 。 下图说明了线程池隔离和信号量隔离的主要区别:
Java虚拟机:SpringCloud的限流、降级和熔断——Hystrix
本文插图

使用线程池时 , 发送请求的线程和执行依赖服务的线程不是同一个 , 而使用信号量时 , 发送请求的线程和执行依赖服务的线程时同一个 ,都是发起请求的线程 。
3、线程隔离总结
线程池和信号量都可以做线程隔离 , 但各有各的优缺点和支持的场景 , 对比如下:

Java虚拟机:SpringCloud的限流、降级和熔断——Hystrix
本文插图

线程池和信号量都支持熔断和限流 。 相比线程池 , 信号量不需要线程切换 , 因此避免了不必要的开销 。 但是信号量不支持异步 , 也不支持超时 , 也就是说当所请求的服务不可用时 , 信号量会控制超过限制的请求立即返回 , 但是已经持有信号量的线程只能等待服务响应或从超时中返回 , 即可能出现长时间等待 。 线程池模式下 , 当超过指定时间未响应的服务 ,Hystrix会通过响应中断的方式通知线程立即结束并返回 。
Java虚拟机:SpringCloud的限流、降级和熔断——Hystrix
本文插图

(二)熔断器
现实生活中 , 可能大家都有注意到家庭电路中通常会安装一个保险盒 , 当负载过载时 , 保险盒中的保险丝会自动熔断 , 以保护电路及家里的各种电器 , 这就是熔断器的一个常见例子 。 Hystrix中的熔断器(Circuit Breaker)也是起类似作用 , Hystrix在运行过程中会向每个commandKey对应的熔断器报告成功、失败、超时和拒绝的状态 , 熔断器维护并统计这些数据 , 并根据这些统计信息来决策熔断开关是否打开 。 如果打开 , 熔断后续请求 , 快速返回 。 隔一段时间(默认是5s)之后熔断器尝试半开 , 放入一部分流量请求进来 , 相当于对依赖服务进行一次健康检查 , 如果请求成功 , 熔断器关闭 。
熔断器配置 , Circuit Breaker主要包括如下6个参数:
1、circuitBreaker.enabled
是否启用熔断器 , 默认是TRUE 。 2 、circuitBreaker.forceOpen
熔断器强制打开 , 始终保持打开状态 , 不关注熔断开关的实际状态 。 默认值FLASE 。 3、circuitBreaker.forceClosed熔断器强制关闭 , 始终保持关闭状态 , 不关注熔断开关的实际状态 。 默认值FLASE 。
4、circuitBreaker.errorThresholdPercentage错误率 , 默认值50% , 例如一段时间(10s)内有100个请求 , 其中有54个超时或者异常 , 那么这段时间内的错误率是54% , 大于了默认值50% , 这种情况下会触发熔断器打开 。
5、circuitBreaker.requestVolumeThreshold
默认值20 。 含义是一段时间内至少有20个请求才进行errorThresholdPercentage计算 。 比如一段时间了有19个请求 , 且这些请求全部失败了 , 错误率是100% , 但熔断器不会打开 , 总请求数不满足20 。
6、circuitBreaker.sleepWindowInMilliseconds
半开状态试探睡眠时间 , 默认值5000ms 。 如:当熔断器开启5000ms之后 , 会尝试放过去一部分流量进行试探 , 确定依赖服务是否恢复 。
(三)熔断器工作原理
下图展示了HystrixCircuitBreaker的工作原理:
Java虚拟机:SpringCloud的限流、降级和熔断——Hystrix
本文插图

熔断器工作的详细过程如下:
第一步 , 调用 allowRequest() 判断是否允许将请求提交到线程池


推荐阅读