Netflix Hystrix - Command执行流程

103 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。


Hystrix执行流程步骤

1. 构造Command

2. 调用command#execute()

3. 检查是否开启缓存

4. 检查是否开启了断路器

5. 检查是否限流

6. 执行command#run()

7. 短路健康检查

8. 调用fallback降级机制

1. 构建一个HystrixCommand或者HystrixObservableCommand

一个HystrixCommand或一个HystrixObservableCommand对象,代表了对某个依赖服务发起的一次请求或者调用

构造的时候,在构造函数中传入需要的参数。

HystrixCommand主要用于仅仅会返回一个结果的调用

HystrixObservableCommand主要用于可能会返回多条结果的调用

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

2. 调用command的执行方法

执行Command就可以发起一次对依赖服务的调用

要执行Command,需要在4个方法中选择其中的一个:execute(),queue(),observe(),toObservable()

其中execute()和queue()仅仅对HystrixCommand适用

execute():调用后直接block住,属于同步调用,直到依赖服务返回单条结果,或者抛出异常

queue():返回一个Future,属于异步调用,后面可以通过Future获取单条结果

observe():订阅一个Observable对象,Observable代表的是依赖服务返回的结果,获取到一个代表结果的Observable对象的拷贝对象(hot observable)

toObservable():返回一个Observable对象,如果我们订阅这个对象,就会执行command并且获取返回结果(cold observable)

K value   = command.execute();
Future<K> fValue  = command.queue();
Observable<K> ohValue = command.observe();         
Observable<K> ocValue = command.toObservable();    

execute()实际上会调用queue().get().queue(),接着会调用toObservable().toBlocking().toFuture()

无论是哪种执行command的方式,最终都是依赖toObservable()去执行的

3. 检查是否开启缓存

如果command开启了请求缓存,而且调用的结果在缓存中存在,直接从缓存中返回结果

4. 检查断路器是否开启

检查command对应的依赖服务断路器是否开启

如果断路器被打开,hystrix就不会执行command,而是直接去执行fallback降级机制

5. 限流

检查线程池/队列/semaphore是否已经满了

如果command对应的线程池/队列/semaphore已经满了,那么也不会执行command,而是直接去调用fallback降级机制

6. 执行command

调用HystrixObservableCommand.construct()或HystrixCommand.run()执行command真正请求逻辑

HystrixCommand.run()是返回一个单条结果,或者抛出一个异常

HystrixObservableCommand.construct()是返回一个Observable对象,可以获取多条结果

如果HystrixCommand.run()或HystrixObservableCommand.construct()的执行,超过了timeout时长的话,那么command所在的线程就会抛出一个TimeoutException

如果timeout,会去执行fallback降级机制,而且不会管run()或construct()返回的值。

不可能终止掉一个调用严重延迟的依赖服务的线程,只能抛出来一个TimeoutException。可能会因为严重延迟的调用线程占满整个线程池。

如果调用依赖服务获取到结果,无论是fallback机制还是command执行成功,hystrix会做一些logging记录和metric统计

7. 断路健康检查

Hystrix会将每一个依赖服务的调用成功,失败,拒绝,超时等事件,发送给circuit breaker断路器。

断路器会对调用成功/失败/拒绝/超时等事件的次数进行统计。

断路器会根据统计次数决定,是否要开启断路。如果打开了断路器,那么在一段时间内就会直接段路请求,然后如果在之后第一次检查发现调用成功,就关闭断路器。

8. 调用fallback降级机制

hystrix调用fallback降级机制:

断路器打开;

限流(线程池/队列/semaphore满了);(reject)

command执行超时;(timeout)

run()或construct()抛出一个异常;(error)

一般在降级机制中,都建议给出一些默认的返回值,比如静态的一些代码逻辑,或者从内存中的缓存中提取一些数据,尽量在这里不要再进行网络请求。

即使在降级中,一定要进行网络调用,也应该将网络请求调用放在一个HystrixCommand中,进行隔离。

在HystrixCommand中,上线getFallback()方法,可以提供降级机制。

在HystirxObservableCommand中,实现一个resumeWithFallback()方法,返回一个Observable对象,可以返回降级结果。

对于HystrixCommand,会返回一个Observable对象,其中会发返回对应的结果

对于HystrixObservableCommand,会返回一个原始的Observable对象,如果没有实现fallback,或者是fallback抛出了异常,Hystrix会返回一个Observable,但是不会返回任何数据

不同的command执行方式,其fallback为空或者异常时的返回结果不同

对于execute(),直接抛出异常

对于queue(),返回一个Future,调用get()时抛出异常

对于observe(),返回一个Observable对象,但是调用subscribe()方法订阅它时,理解抛出调用者的onError方法

对于toObservable(),返回一个Observable对象,但是调用subscribe()方法订阅它时,理解抛出调用者的onError方法

command不同的执行方式

execute(),获取一个Future.get(),然后拿到单个结果

queue(),返回一个Future

observer(),立即订阅Observable,然后启动8大执行步骤,返回一个拷贝的Observable,订阅时立即回调返回结果

toObservable(),返回一个原始的Observable,必须手动订阅才会去执行8大步骤。