一,hystrix整体流程
- 构造一个 HystrixCommand或HystrixObservableCommand对象,用于封装请求,并在构造方法中配置请求被执行需要的参数;
- 执行命令,Hystrix提供了4种执行命令的方法
- 判断是否使用缓存响应请求,若启用了缓存,且缓存可用,直接使用缓存响应请求。Hystrix支持请求缓存,但需要用户自定义启动;
- 判断熔断器是否打开,如果打开,执行第8步;
- 判断线程池/队列/信号量是否已满,已满则执行第8步;
- 执行HystrixObservableCommand.construct()或HystrixCommand.run(),如果执行失败或者超时,执行第8步;否则,跳到第9步;
- 统计熔断器监控指标;
- 走Fallback备用逻辑
- 返回请求响应
注意:1.第5步线程池/队列/信号量已满时,还会执行第7步逻辑,更新熔断器统计信息,而第6步无论成功与否,都会更新熔断器统计信息。2.可以通过重载getCacheKey()方法来开启请求缓存。如果涉及到数据修改则需要在修改的进修清除缓存,通过HystrixRequestCache.clear方法清除。
hystrxi设计理念
- 使用命令模式将所有对外部服务(或依赖关系)的调用包装在HystrixCommand或HystrixObservableCommand对象中,并将该对象放在单独的线程中执行;
- 每个依赖都维护着一个线程池(或信号量),线程池被耗尽则拒绝请求(而不是让请求排队)。
- 记录请求成功,失败,超时和线程拒绝。
- 服务错误百分比超过了阈值,熔断器开关自动打开,一段时间内停止对该服务的所有请求。
- 请求失败,被拒绝,超时或熔断时执行降级逻辑。
- 近实时地监控指标和配置的修改。
二,hystrix容错
一,资源隔离
资源隔离主要指对线程的隔离。Hystrix提供了两种线程隔离方式:线程池和信号量,默认为线程池。
使用线程池时,发送请求的线程和执行依赖服务的线程不是同一个;而使用信号量时,发送请求的线程和执行依赖服务的线程是同一个,都是发起请求的线程。
线程切换 | 支持异步 | 支持超时 | 支持熔断 | 限流 | 开销 | |
---|---|---|---|---|---|---|
信号量 | 否 | 否 | 否 | 是 | 是 | 小 |
线程池 | 是 | 是 | 是 | 是 | 是 | 大 |
线程池和信号量都支持熔断和限流。
相比线程池,信号量不需要线程切换,如果是tomcat服务,那信号量使用的就是tomcat的线程而线程池则是tomcat线程创建的线程池,因此避免了不必要的开销。
但是信号量不支持异步,也不支持超时,也就是说当所请求的服务不可用时,信号量会控制超过限制的请求立即返回,但是已经持有信号量的线程只能等待服务响应或从超时中返回,即可能出现长时间等待。线程池模式下,当超过指定时间未响应的服务,Hystrix会通过响应中断的方式通知线程立即结束并返回。
基于上面两者的特点,我们可以知道它们分别适用的场景:
- 信号量 请求并发大且耗时短(本服务的内存操作等);不会访问依赖外部的服务,因为信号量是不支持超时的,它处理不了timeout的问题
- 线程池 请求并发大且耗时长;因为线程池是支持超时的,所以访问的服务是否依赖外部都行;如果应用恰好适合异步执行那线程池会是一个不错的选择。当然线程池也是需要维护的所以线程上下文切换也会有开销
二,熔断
熔断器里6个重要的参数:
- circuitBreaker.enabled
是否启用熔断器,默认是TRUE。 - circuitBreaker.forceOpen
熔断器强制打开,始终保持打开状态,不关注熔断开关的实际状态。默认值FLASE。 - circuitBreaker.forceClosed
熔断器强制关闭,始终保持关闭状态,不关注熔断开关的实际状态。默认值FLASE。 - circuitBreaker.errorThresholdPercentage
错误率,默认值50%,例如一段时间(10s)内有100个请求,其中有54个超时或者异常,那么这段时间内的错误率是54%,大于了默认值50%,这种情况下会触发熔断器打开。 - circuitBreaker.requestVolumeThreshold
默认值20。含义是一段时间内至少有20个请求才进行errorThresholdPercentage计算。比如一段时间了有19个请求,且这些请求全部失败了,错误率是100%,但熔断器不会打开,总请求数不满足20。 - circuitBreaker.sleepWindowInMilliseconds
半开状态试探睡眠时间,默认值5000ms。如:当熔断器开启5000ms之后,会尝试放过去一部分流量进行试探,确定依赖服务是否恢复。
断路开启,也就是由 close 转换到 open 状态(close -> open)。那么之后在 SleepWindowInMilliseconds 时间内(默认值5000ms),所有经过该断路器的请求全部都会被断路,不调用后端服务,直接走 fallback 降级机制。
而在该参数时间过后,断路器会变为 half-open 半开闭状态,尝试让一条请求经过断路器,看能不能正常调用。如果调用成功了,那么就自动恢复,断路器转为 close 状态。
三,降级
降级,通常指务高峰期,为了保证核心服务正常运行,需要停掉一些不太重要的业务,或者某些服务不可用时,执行备用逻辑从故障服务中快速失败或快速返回,以保障主体业务不受影响。Hystrix提供的降级主要是为了容错,保证当前服务不受依赖服务故障的影响,从而提高服务的健壮性。要支持回退或降级处理,可以重写HystrixCommand的getFallBack方法或HystrixObservableCommand的resumeWithFallback方法。
Hystrix在以下几种情况下会走降级逻辑:
- 执行construct()或run()抛出异常
- 熔断器打开导致命令短路
- 命令的线程池和队列或信号量的容量超额,命令被拒绝
- 命令执行超时
降级回退方式有多种,这里列举两种:
- 快速失败,快速失败是最普通的命令执行方法,命令没有重写降级逻辑。 如果命令执行发生任何类型的故障,它将直接抛出异常。
- 无声失败,指在降级方法中通过返回null,空Map,空List或其他类似的响应来完成。
我们可以根据自己的业务需要开发降级方案,但是需要注意下降级逻辑是否会出异常的可能。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。