解读Hystrix系列(二):Hystrix详细工作原理

承接上篇内容本节具体聊聊Hystrix详细的工作原理以及内部实现流程。

Hystrix向服务依赖项发出请求时会发生什么?

hystrix-command-flow-chart.png
1. 构造一个HystrixCommand或HystrixObservableCommand对象

第一步是构造一个HystrixCommand或HystrixObservableCommand对象来表示对依赖项的请求。将请求发出时需要的任何参数传递给构造函数。
构造一个 HystrixCommand 对象 如果依赖期望返回一个单个响应. 例如:
HystrixCommand command = new HystrixCommand(HystrixCommandGroupKey group, HystrixThreadPoolKey threadPool);
构造一个 HystrixObservableCommand 对象 如果期望依赖项返回发出响应的Observable对象.例如:
HystrixObservableCommand ObservableCommand = new HystrixObservableCommand(HystrixCommandGroupKey group)

2. 执行命令

有四种方法可以执行命令,使用以下四种方法之一的Hystrix命令对象(前两种方法只适用于简单的HystrixCommand对象,不适用于HystrixObservableCommand):

  • execute() — blocks, 返回从依赖项接收到的单个响应(或在出现错误时抛出异常)
  • queue() — 返回一个Future值,使用该将来值可以从依赖项获得单个响应
  • observe() — 订阅表示来自依赖项的响应的Observable 对象,并返回复制源observable对象的observable对象。
  • toObservable() — 返回一个可观察对象,当您订阅它时,它将执行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都由一个可观察到的实现支持,即使是那些打算返回单个简单值的命令。

3.是否缓存了响应?

如果为该命令启用了请求缓存,并且在缓存中可用对请求的响应,则此缓存的响应将立即以可观察到的形式返回。(请参阅下面的Request Caching)。

4. Circuit 是否打开?

当您执行该命令时,Hystrix将与断路器一起检查电路是否打开。
如果电路打开(或“跳闸”),那么Hystrix将不执行命令,而是将流路由到(8)获取回退。
如果电路被关闭,则流继续到(5),检查是否有可用的容量来运行命令。

5.Thread Pool/Queue/Semaphore 是否已满?

如果与该命令关联的线程池和队列(或信号量,如果不在线程中运行)已满,那么Hystrix将不执行该命令,而是立即将流路由到(8)获取回退。

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

这里,Hystrix通过为此目的编写的方法调用对依赖项的请求,方法如下:

如果run()或construct()方法超过命令的超时值,线程将抛出一个TimeoutException(如果命令本身不在自己的线程中运行,则单独的计时器线程将抛出一个TimeoutException)。在这种情况下,Hystrix将响应路由到8。获取回退,如果最终返回值run()或construct()方法没有取消/中断,那么它将丢弃该方法。

请注意,没有办法强制潜在线程停止工作——Hystrix在JVM上能做的最好的事情就是抛出InterruptedException。如果由Hystrix包装的工作不尊重interruptedexception,那么Hystrix线程池中的线程将继续它的工作,尽管客户机已经收到了TimeoutException。这种行为可能会使Hystrix线程池饱和,尽管负载“正确释放”。大多数Java HTTP客户端库不解释interruptedexception。因此,请确保正确配置HTTP客户机上的连接和读/写超时。

7. 计算电路健康

Hystrix向断路器报告成功、失败、拒绝和超时,断路器维护一组滚动计数器,用于计算统计数据。它使用这些统计数据来确定电路应该在什么时候断路,在这一点上,它会短路任何后续的请求,直到恢复期结束,在此期间,它会在第一次检查某些健康检查之后再次关闭电路。

8. Get the Fallback

Hystrix试图恢复你的回滚命令执行失败时:当一个异常的构造()或()运行(6),当命令电路短路,因为打开(4),当命令的线程池和队列或信号能力(5),或者当命令已超过其超时长度。
编写回退以提供来自内存缓存或其他静态逻辑的通用响应,而不需要任何网络依赖。如果必须在回退中使用网络调用,则应该使用另一个HystrixCommand或HystrixObservableCommand。

对于HystrixCommand,要提供回退逻辑,可以实现HystrixCommand. getfallback(),它返回一个回退值。

对于HystrixObservableCommand,要提供回退逻辑,可以实现HystrixObservableCommand. resumewithfallback(),它返回一个可观察的对象,该对象可能会发出一个或多个回退值。

如果回退方法返回一个响应,那么Hystrix将把这个响应返回给调用者。在HystrixCommand.getFallback()的情况下,它将返回一个可观察的对象,该对象发出方法返回的值。在hystrixobservablecomman . resumewithfallback()的情况下,它将返回方法返回的相同的可观察值。

如果您还没有为您的Hystrix命令实现回退方法,或者回退本身引发异常,Hystrix仍然返回一个可观察到的方法,但是该方法不发出任何东西,并立即以onError通知终止。正是通过这个onError通知,导致命令失败的异常才被传输回调用者。(实现可能失败的回退实现是一种糟糕的实践。您应该实现回退,这样它就不会执行任何可能失败的逻辑。

失败或不存在回退的结果将根据您如何调用Hystrix命令而有所不同:

  • execute() — throws an exception
  • queue() — 成功返回一个Future,但是如果调用它的get()方法,这个Future将抛出异常
  • observe() — 返回一个可观察到的对象,当您订阅该对象时,将通过调用订阅方的onError方法立即终止该对象
  • toObservable() — 返回一个可观察对象,当您订阅该对象时,它将通过调用订阅方的onError方法终止
9. 返回成功的响应

如果Hystrix命令成功,它将以可观察到的形式返回响应或响应给调用者。根据您如何调用上面步骤2中的命令,这个可观察对象可能在返回给您之前进行转换:


hystrix-return-flow-640.png
  • execute() — 以与.queue()相同的方式获取一个Future,然后在这个 Future上调用get()来获取可观察对象发出的单个值
  • queue() — 将可观察对象转换为BlockingObservable,以便将其转换为未来,然后返回此未来
  • observe() — 立即订阅可观察对象,并开始执行命令的流;返回一个可观察对象,当您订阅该对象时,将重播排放和通知
  • toObservable() — 返回可观察值不变;您必须订阅它,才能真正开始执行命令的流程
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342