写代码的必选项:正确性、可读性、可测试性。可选项:性能、资源开销
代码下载地址:https://github.com/f641385712/netflix-learning
上篇文章 介绍了Hystrix事件计数器EventCounts和执行结果ExecutionResult
,它帮忙记录着执行过程中的事件计数以及各种时间、状态等结果。本文将要介绍命令执行过程中的核心接口,包括同步执行方法、异步执行方法以及基于RxJava的Observable
执行方式。
本篇内容仅会着眼于接口层面进行描述,从大的框架方面去掌握Hystrix的设计,这样后面仅需以一个“实现类”举例便可举一反三了。
我们知道Hystrix是以命令模式执行目标方法的,也就是每个目标方法最终都会被封装成为一个command对象。但整体上它分为两个系列,它们的继承图表如下:
xxxCommand
系列:
xxxCollapser
系列:
二者实现的接口具有共通性,本篇文章将对这些核心接口进行解释说明。
它是个纯标记接口,无任何方法:表示Hystrix commands
可以被invoke。
public interface HystrixInvokable<R> {
}
它虽然没有方法但带有一个泛型R:代表命令返回值。它有两个子接口:HystrixExecutable
和HystrixObservable
。
HystrixCommand
和HystrixCollapser
均实现了此接口,以便于对它俩进行公共处理。
public interface HystrixExecutable<R> extends HystrixInvokable<R> {
// 同步执行,原理是:queue().get() 所以效果是同步的
public R execute();
// 异步执行,什么时候get由调用者决定。get的时候才会阻塞:获取结果或者错误
// 其实queue的原理是toObservable().toBlocking().toFuture()
public Future<R> queue();
// 异步执行。toObservable().subscribe(subject) subject=ReplaySubject
// 原理也是基于toObservable(),但是它是立马执行,且有回放的能力
public Observable<R> observe();
}
该接口正如其名:Executable
可执行的。提供同步执行方法,异步执行的Futrue,以及基于RxJava的Observable
可观察对象。正如注释中所言:它们的实现原理均是基于toObservable()
方法。该接口实现类有且仅有HystrixCommand
和HystrixCollapser
两个。
说明:
HystrixObservableCommand
和HystrixObservableCollapser
并不实现它,而是实现的HystrixObservable
接口。
同样的,它的目的也是为了抽取公共实现,它强调于HystrixObservable
。
可以看到,使用者能接触到的所有的子类都有实现于它。它强调Observable
,期望通过订阅式实现异步获取结果。
public interface HystrixObservable<R> extends HystrixInvokable<R> {
public Observable<R> observe();
public Observable<R> toObservable();
}
两个方法看似一样,都是得到一个Observable
,但有些许差异:
observe()
:提供饥饿模式的Observable实例:它会立马启动执行HystrixCommand#queue() / execute()
命令,并且执行回放ReplaySubject<R>
toObservable()
:提供Lazy/defer延迟模式的Observable实例:只有在订阅了Observable
之后,才惰性地开始执行命令需要特别关心的是toObservable()
方法,它是所有的执行方法的基石,一切都源于它。
最后来看看xxxCmmand
系列实现的一个特殊接口:HystrixInvokableInfo
。
在xxxCommand
系列还有一个接口,它便是HystrixInvokableInfo
。从命名上看,它好似表示HystrixInvokable
的一些详细信息,而实际情况也确实如此。该接口提供大量的get类型的方法获取各种各样的值,而这些方法所需要的信息大多在执行结果ExecutionResult
这个POJO里。
说明:关于
ExecutionResult
的详解,请移步上篇文章
public interface HystrixInvokableInfo<R> {
// 获取各种key:
// CommandKey:命令的id
// CommandGroupKey:逻辑分组的key
// ThreadPoolKey:线程池分组的key。不指定默认使用CommandGroupKey的值
// CollapserKey:合并的id
HystrixCommandGroupKey getCommandGroup();
HystrixCommandKey getCommandKey();
HystrixThreadPoolKey getThreadPoolKey();
HystrixCollapserKey getOriginatingCollapserKey();
// 内部实际调用protected的AbstractCommand#getCacheKey()方法
// 就是把这个方法public掉的作用
String getPublicCacheKey()
// 获取command的指标信息(该类前面已经重点介绍过了)
HystrixCommandMetrics getMetrics();
// HystrixCommand的配置信息:非常多的属性可定制
// 实现:init初始化,一般来源于SPI机制
HystrixCommandProperties getProperties();
// 断路器是否打开:由HystrixCommandProperties配置以及circuitBreaker.isOpen()共同决定
boolean isCircuitBreakerOpen();
// 执行是否完成:commandState命令状态是否是TERMINAL状态:
boolean isExecutionComplete();
// 是否在隔离线程里执行的任务
// ExecutionResult#isExecutedInThread()
boolean isExecutedInThread();
// 是否执行成功。
// ExecutionResult#getEventCounts().contains(HystrixEventType.SUCCESS)
boolean isSuccessfulExecution();
// 实现:ExecutionResult#getEventCounts().contains(HystrixEventType.FAILURE)
boolean isFailedExecution();
// 若失败了,获取其异常信息
// 实现:executionResult.getException();
Throwable getFailedExecutionException();
// 是否是fallback了
// 实现:ExecutionResult#getEventCounts().contains(HystrixEventType.FALLBACK_SUCCESS)
boolean isResponseFromFallback();
// 实现:ExecutionResult#getEventCounts().contains(HystrixEventType.TIMEOUT)
boolean isResponseTimedOut();
// short-circuited:短路
// isCircuitBreakerOpen() == true并且结果来自于fallabck,这就叫直接短路了(根本不走你目标方法)
// 实现:ExecutionResult#getEventCounts().contains(HystrixEventType.SHORT_CIRCUITED)
boolean isResponseShortCircuited();
// 结果是否来自于缓存。若true,那么run()将不会被执行
boolean isResponseFromCache();
// 拒绝:响应是否是被拒绝后的回退(请注意:没有执行run方法)
// 包括线程池拒绝和信号量拒绝
// 实现:ExecutionResult#isResponseRejected()
boolean isResponseRejected();
boolean isResponseSemaphoreRejected()
boolean isResponseThreadPoolRejected()
// 执行过程中,所有被记录过的事件们(没被记录过的就木有)
// 实现ExecutionResult#getOrderedList()
List<HystrixEventType> getExecutionEvents()
// 命令执行过程中的发射次数。
// ExecutionResult#getEventCounts().getCount(HystrixEventType.EMIT);
int getNumberEmissions();
int getNumberFallbackEmissions();
int getNumberCollapsed();
// 此command实例的执行时间(以毫秒为单位),如果未执行,则为-1。
// 实现:ExecutionResult#getExecutionLatency
int getExecutionTimeInMilliseconds();
// 调用该command实例的run方法的时刻纳秒,如果没有执行,则为-1
// 实现:ExecutionResult#getCommandRunStartTimeInNanos
long getCommandRunStartTimeInNanos();
// EventCounts对象是对事件类型的的一个计数、统计
// 实现ExecutionResult#getEventCounts()
ExecutionResult.EventCounts getEventCounts()
}
虽说该接口实现类仅有HystrixCommand
和HystrixObservableCommand
,但它的所有的方法实现均在其父类AbstractCommand
里,并且大多数都委托给执行结果ExecutionResult
去完成,这就是为何要有上篇文章的原因喽。
AbstractCommand
抽象类里,其子类HystrixCommand/HystrixObservableCommand
均无需关心ExecutionResult
去实现。关于Hystrix执行过程核心接口:HystrixExecutable、HystrixObservable和HystrixInvokableInfo就介绍到这了,本文的目的有两个:
HystrixInvokableInfo
接口,和ExecutionResult
产生联系