Flow Chart
下图显示了通过Hystrix向服务依赖项发出请求时发生的情况:
以下部分将更详细地解释此流程:
- Construct a
HystrixCommand
orHystrixObservableCommand
Object - Execute the Command
- Is the Response Cached?
- Is the Circuit Open?
- Is the Thread Pool/Queue/Semaphore Full?
HystrixObservableCommand.construct()
orHystrixCommand.run()
- Calculate Circuit Health
- Get the Fallback
- Return the Successful Response
1. Construct a HystrixCommand
or HystrixObservableCommand
Object
第一步是构造一个HystrixCommand或HystrixObservableCommand对象来表示您对依赖项的请求。传递构造函数在发出请求时需要的任何参数。
如果期望依赖项返回单个响应,则构造HystrixCommand对象。例如:
HystrixCommand command = new HystrixCommand(arg1, arg2);
如果期望依赖项返回发出响应的Observable,则构造HystrixObservableCommand对象。例如:
HystrixObservableCommand command = new HystrixObservableCommand(arg1, arg2);
2. Execute the Command
通过使用Hystrix命令对象的以下四种方法之一,有四种方法可以执行命令(前两种方法仅适用于简单的HystrixCommand对象,不适用于HystrixObservableCommand):
- execute() - blocks,然后返回从依赖项收到的单个响应(或者在发生错误时抛出异常)
- queue() - 返回一个Future,您可以使用它从依赖项中获取单个响应
- observe() - 订阅表示来自依赖项的响应的Observable,并返回一个Observable,它复制该源Observableto
- Observable() - 返回一个Observable,当您订阅它时,它将执行Hystrix命令并发出其响应
K value = command.execute();
Future<K> fValue = command.queue();
Observable<K> ohValue = command.observe(); //hot observable
Observable<K> ocValue = command.toObservable(); //cold observable
同步调用execute()调用queue()。get()。queue()依次调用toObservable()。toBlocking()。toFuture()。也就是说,最终每个HystrixCommand都支持Observable实现,甚至那些旨在返回单个简单值的命令。
3. Is the Response Cached?
如果为此命令启用了请求缓存,并且如果缓存中有对请求的响应,则此缓存响应将立即以Observable的形式返回。(请参阅下面的“请求缓存”。)
4. Is the Circuit Open?
当您执行命令时,Hystrix会检查断路器以查看电路是否打开。如果电路打开(或“跳闸”),则Hystrix将不执行命令,但会将流程路由到(8)获取后备。如果电路闭合,则流程进行到(5)以检查是否有可用于运行命令的容量。
5. Is the Thread Pool/Queue/Semaphore Full?
如果与该命令关联的线程池和队列(或信号量,如果未在线程中运行)已满,则Hystrix将不会执行该命令,但会立即将流路由到(8)获取后备。
6. HystrixObservableCommand.construct()
or HystrixCommand.run()
在这里,Hystrix通过您为此目的编写的方法调用对依赖项的请求,其中一项如下:
HystrixCommand.run() - 返回单个响应或抛出异常
HystrixObservableCommand.construct() - 返回发出响应或发送onError通知的Observable
如果run()或construct()方法超出命令的超时值,则线程将抛出TimeoutException(如果命令本身未在其自己的线程中运行,则将抛出单独的计时器线程)。在这种情况下,Hystrix将响应路由到8.获取回退,如果该方法不取消/中断,它将丢弃最终返回值run()或construct()方法。
请注意,没有办法强制潜在的线程停止工作 - 最好的Hystrix可以在JVM上做的就是抛出InterruptedException。如果由Hystrix包装的工作不遵守InterruptedExceptions,则Hystrix线程池中的线程将继续其工作,尽管客户端已经收到TimeoutException。这种行为可以使Hystrix线程池饱和,尽管负载“正确脱落”。大多数Java HTTP客户端库不解释InterruptedExceptions。因此,请确保在HTTP客户端上正确配置连接和读/写超时。
如果该命令没有抛出任何异常并且它返回了响应,则Hystrix在执行一些日志记录和度量报告后返回此响应。在run()的情况下,Hystrix返回一个Observable,它发出单个响应,然后发出onCompleted通知;在construct()的情况下,Hystrix返回由construct()返回的相同Observable。
7. Calculate Circuit Health
Hystrix报告断路器的成功,失败,拒绝和超时,它维护着一组计算统计数据的计数器。
它使用这些统计数据来确定电路何时“跳闸”,此时它会使任何后续请求短路,直到恢复周期结束,然后在首次检查某些健康检查后再次关闭电路。