[享学Netflix] 二十九、Hystrix执行过程核心接口:HystrixExecutable、HystrixObservable和HystrixInvokableInfo

写代码的必选项:正确性、可读性、可测试性。可选项:性能、资源开销

–> 返回专栏总目录 <–
代码下载地址:https://github.com/f641385712/netflix-learning

前言

上篇文章 介绍了Hystrix事件计数器EventCounts和执行结果ExecutionResult,它帮忙记录着执行过程中的事件计数以及各种时间、状态等结果。本文将要介绍命令执行过程中的核心接口,包括同步执行方法、异步执行方法以及基于RxJava的Observable执行方式。

本篇内容仅会着眼于接口层面进行描述,从大的框架方面去掌握Hystrix的设计,这样后面仅需以一个“实现类”举例便可举一反三了。


正文

我们知道Hystrix是以命令模式执行目标方法的,也就是每个目标方法最终都会被封装成为一个command对象。但整体上它分为两个系列,它们的继承图表如下:

xxxCommand系列:

在这里插入图片描述
xxxCollapser系列:

在这里插入图片描述
二者实现的接口具有共通性,本篇文章将对这些核心接口进行解释说明。


HystrixInvokable

它是个纯标记接口,无任何方法:表示Hystrix commands可以被invoke。

public interface HystrixInvokable<R> {
}

它虽然没有方法但带有一个泛型R:代表命令返回值。它有两个子接口:HystrixExecutableHystrixObservable

扫描二维码关注公众号,回复: 10162779 查看本文章

HystrixExecutable

HystrixCommandHystrixCollapser均实现了此接口,以便于对它俩进行公共处理。
在这里插入图片描述

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()方法。该接口实现类有且仅有HystrixCommandHystrixCollapser两个。

说明:HystrixObservableCommandHystrixObservableCollapser并不实现它,而是实现的HystrixObservable接口。


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

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()

}

虽说该接口实现类仅有HystrixCommandHystrixObservableCommand,但它的所有的方法实现均在其父类AbstractCommand里,并且大多数都委托给执行结果ExecutionResult去完成,这就是为何要有上篇文章的原因喽。

  • 该接口所有的方法实现均在AbstractCommand抽象类里,其子类HystrixCommand/HystrixObservableCommand均无需关心
  • 大多数方法都是获取执行完成后的结果数据/状态数据,所以大多数方法都是委托给ExecutionResult去实现。

总结

关于Hystrix执行过程核心接口:HystrixExecutable、HystrixObservable和HystrixInvokableInfo就介绍到这了,本文的目的有两个:

  • 面向接口理解Hystrix的设计框架,更全面的掌握Hystrix的架构设计
  • 详解HystrixInvokableInfo接口,和ExecutionResult产生联系
    分隔线

声明

原创不易,码字不易,多谢你的点赞、收藏、关注。把本文分享到你的朋友圈是被允许的,但拒绝抄袭。你也可【左边扫码/或加wx:fsx641385712】邀请你加入我的 Java高工、架构师 系列群大家庭学习和交流。
往期精选

发布了362 篇原创文章 · 获赞 531 · 访问量 48万+

猜你喜欢

转载自blog.csdn.net/f641385712/article/details/104528514
今日推荐