Hystrix是如何工做的

接上一篇:《Hystrix介绍html

流程图

下面这幅图至关重要git

稍微解释一下上面的流程:github

  1. Construct a HystrixCommand or HystrixObservableCommand Object
  2. Execute the Command
  3. Is the Response Cached?
  4. Is the Circuit Open?
  5. Is the Thread Pool/Queue/Semaphore Full?
  6. HystrixObservableCommand.construct() or HystrixCommand.run()
  7. Calculate Circuit Health
  8. Get the Fallback
  9. Return the Successful Response

 

1. 构造一个HystrixCommand或者HystrixObservableCommand对象

第一步是构造一个HystrixCommand或HystrixObservableCommand对象来表示对依赖项的请求。例如:缓存

HystrixCommand command = new HystrixCommand(arg1, arg2);
HystrixObservableCommand command = new HystrixObservableCommand(arg1, arg2);

 2. 执行命令

 你能够用下列四种中的任意一种方式执行命令:并发

  • execute() — 阻塞,直到收到响应或者抛出异常.
  • queue() — 返回一个Future
  • observe() — 订阅表明响应的Observable
  • toObservable() — 返回一个Observable,当你订阅它之后,将会执行Hystrix命令而且推送它的响应

execute()方法是同步执行的,它是调用queue().get()异步

queue()方法是异步执行的,它调用的是toObservable().toBlocking().toFuture()性能

因此最终每一个HystrixCommand都是一个Observable的实现ui

3. 响应是否已经被缓存?

若是请求在缓存中可用,而且该请求对应的响应在缓存中也是可用的,那么缓存的这个响应将当即以一个Observable的形式被返回spa

4. 断路器是否打开?

当你执行命令的时候,Hystrix检查断路器是不是开着的。若是是开着的,那么Hystrix不会执行命令,而是路由到第8步执行回退逻辑。若是是关着的,将执行第5步,继续检查容量是否可用。线程

5. 线程池/队列/信号量是否已经满了?

若是这个命令所关联的线程池和队列(或者信号量)是否满了,若是是,那么Hystrix不会执行命令,而是当即路由到第8不执行回退逻辑

6. HystrixObservableCommand.construct() or HystrixCommand.run()

咱们知道对依赖的调用请求都是封装成HystrixCommand或者HystrixObservableCommand执行的,而真正执行的逻辑是写在HystrixObservableCommand.construct()或者HystrixCommand.run()中的:

  • HystrixCommand.run() — 返回一个响应或者抛出一个异常
  • HystrixObservableCommand.construct() — 返回一个Observable,而且推送响应或者发送一个onError通知

若是在执行run()或者construct()方法超时,那么线程将抛出一个TimeoutException。

7. 计算电路健康

Hystrix报告成功、失败、拒绝、超时给断路器,断路器维护一组计算统计的计数器。

断路器用这些统计数据来决定何时应该“跳闸”,此时后续全部的请求都会被短路,直到一个恢复周期耗尽之后在第一次检查某些健康检查以后才会打开电路。

(PS:想象一下生活中的漏电保护器,电压太高时会自动跳闸,跳闸之后就没电了,家用电器都用不了了,以后你能够本身不去合上,固然前提是你不能再用那些大功率电器了,因而来电了)

8. 回退

当命令执行失败时,Hystrix试图恢复到您的fallback:当run()或者construct()抛出异常;当因为断路器跳闸致使命令被短路;当命令的线程池或队列容量满了;或者当命令执行超时。

在HystrixCommand的状况下,为了提供回退逻辑,你能够实现HystrixCommand.getfallback(),它返回一个单一的回退值。

对于HystrixObservableCommand(),为了提供回退逻辑,你须要实现hystrixobservablecomman.resumewithfallback(),它会返回一个Observable,这个Observable可能返回一个回退值或者多个值。

若是你没有实现一个fallback方法,或者fallback它本身抛了一个异常,此时Hystrix仍然会返回一个Observable,可是这个Observable什么都不会推送并当即发送一个onError通知。经过这个onError通知,形成命令失败的异常会传回给调用者。

9. 返回成功响应

若是Hystrix命令成功,它会返回响应给调用者,或者返回一个Observable。这取决于在第2步的时候你是若是调用命令的。

Circuit Breaker(断路器)

下图显示了HystrixCommand或HystrixObservableCommand是如何与HystrixCircuitBreaker交互的,以及它的逻辑和决策流程,包括断路器中计数器的行为。

上面的流程能够这样描述:

  1. 假设整个电路的体积达到必定的阈值
  2. 假设错误百分比超过设定的错误百分比阈值
  3. 断路器从CLOSED变成OPEN
  4. 当它打开时,通过这个断路器的全部请求被短路
  5. 过了一段时间之后,下一个单个请求被容许经过(此时是半打开状态)。若是这个请求失败,在接下来的睡眠窗口期间断路器保持OPEN状态;若是这个请求成功,断路器转成CLOSED状态;而后继续执行第1步,如此反复。

隔离

Hystrix使用隔板模式来隔离彼此的依赖关系,并限制对其中任何一个的并发访问。

线程和线程池

Hystrix使用独立的、每一个依赖项的线程池做为约束任何给定依赖项的一种方式,所以底层执行的延迟只会使该池中的可用线程饱和。

线程池的好处

  1. 应用程序被彻底保护而不受失控的客户端的影响。给定的依赖项的线程池能够填满,而不会影响应用程序的其他部分。
  2. 应用程序能够接收新的客户端请求
  3. 当失败的客户端再次恢复正常时,线程池将被清理,应用程序将当即恢复正常的性能
  4. 若是一个客户端配置错误,线程池的健康将会很快地证实这一点(经过增长错误、延迟、超时、拒绝等),而且您能够处理它(一般是经过动态属性进行实时处理),而不会影响应用程序的功能。

Semaphores(信号量)

你能够用信号量(或者计数器)来限制对任意依赖项并发调用的数量,代替用线程池的大小。

HystrixCommand 和 HystrixObservableCommand 在两个地方支持用信号量:

  • Fallback:当Hystrix恢复fallbacks时它老是调用Tomcat的线程这样作
  • Execution:若是设置属性execution.isolation.strategy为SEMAPHORE,那么,Hystrix将使用信号量而不是线程来限制调用该命令的发父线程的并数量。

 

https://github.com/Netflix/Hystrix/wiki/How-it-Works

相关文章
相关标签/搜索