44

Hystrix信号量模式支持超时时间吗

 5 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzUzODQ0MDY2Nw%3D%3D&%3Bmid=2247484020&%3Bidx=1&%3Bsn=8b59b9d0b8cfcced481a4db81c0e6b74&%3Butm_source=tuicool&%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

背景

前段时间我司内部晋升答辩时,有位同事的晋升PPT中说到它采用了“Hystrix信号量 + RPC CallBack + CompletableFuture”进行了性能优化,使用Hystrix主要是使用它的超时、降级、熔断等功能。不少评委提出了质疑,因为他们认为Hystrix信号量模式是不支持超时的。

Talk is cheap,Show me your code

信号量模式

MJRVvyV.jpg!web

从实验中我们可以看出,Hystrix的信号量模式确实是支持超时的,但是结论就真的这么简单吗?

对于线程池实现超时比较容易理解,future.get(timeout)就可以了,但是对于信号量该如何实现以及理解呢。

我们接下来继续实验。

yANvIvB.jpg!web

从输出的日志顺序可以看出来,明明是run执行完成之后,才在main方法中接收到的TimeoutException。 也就是说 Hystrix任务会在 main线程中会一直执行Hystrix任务,直到任务执行结束,如果发现执行时间超过了Hytrix设置的超时时间,main线程才会接收到异常。并不是在超时时间内结果Hystrix任务,释放资源。

那么如果实现了fallback又会是什么样子的呢?

jyI36v6.jpg!web

FbEj2mZ.jpg!web

从日志中可以看出,fallback其实任务在到达超时时间(也就是配置的150ms)时,由另外的线程去执行的fallback内容。但是main线程也只能在Hystrix run方法执行完成之后才能获取到fallback中的返回值。

上面的执行路径大概如下:

B7BnIjy.jpg!web

线程池模式

Rnauequ.jpg!web

BJbqiyf.jpg!web

从日志可以看出,对于线程池模式,在到达timeout时候,会有HystrixTimer线程会把运行任务的Hystrix线程设置为中断,然后使用 HystrixTimer线程去之心fallback。

执行路径大概如下:

NRjiymn.jpg!web

那么如果对于运行run方法的代码逻辑如果不支持中断又会怎么样呢?

bM3A3m7.jpg!web

E7rUzeR.jpg!web

虽然运行run方法的线程被设置了中断标志,但是因为run方法本身不支持中断逻辑,所以该线程会一直运行直到任务执行完毕。

为什么很多人认为信号量不支持超时

我想很多人认为信号量不支持超时,应该是来自于Hystrix的官网上诱导,官方上明确提到信号量模式是不支持。

3AZFR3i.jpg!web

看了一下官网上最后一次更新都是两年前了,应该是没有及时更新wiki才会导致很多人出现这个误解。

在早期的时候Hystrix信号量确实是不支持超时时间的,当时仅仅线程池支持,设置超时时间的参数为withExecutionIsolationThreadTimeoutInMilliseconds,但是在1.4.0之后的版本,信号量也就支持了超时时间,此时参数统一修改成了withExecutionIsolationThreadTimeoutInMilliseconds。

BBzyU3B.jpg!web

总结

从上述分析我们可以得出Hystrix的超时机制:

Hystrix在任务启动时会启动另外一个线程HystrixTime去监测任务。如果在TimeOut时间内,任务未完成,对于线程池模式,会把执行任务的线程设置为中断;对于信号量模式,Hystrix不会对执行任务的线程做任何操作。然后再使用HystrixTime线程去执行fallback逻辑。

所以大家一定要明白: 对于信号量超时模式,如果发生超时,Hystrix任务并不会结束,任务结束还是得依赖于run方法执行完毕。

对于线程池超时模式,如果发生超时,Hystrix任务可以结束,不依赖于run方法执行情况,但是run方法可能还会在执行,这依赖与run方法中的代码逻辑。

由此带来哪些问题呢?

  1. 在run方法中加入监控,看到的执行时间可能远大于timeout

  2. 配置的线程数能支持的最小QPS不是简单的”线程数 /  timeout“。

  3. 对于信号量模式,整体串形链路的的最大时间,不是简单的Hystrix1的timeout +  Hystrix2的timeout + ... +  HystrixN的timeout。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK