Hystrix的执行流程和原理

Hystrix是Netflix开源的一款容错框架。

Hystrix [hɪst'rɪks],中文含义是豪猪,因其背上长满棘刺,从而拥有了自我保护的能力。

Hystrix工作原理图

(图来源:https://github.com/Netflix/Hystrix/wiki/How-it-Works

说明:

1.构建一个HystrixCommand或者HystrixObservableCommand对象,将请求包装到Command对象中。
2.执行命令。
3.判断当前请求是否有缓存,如果在缓存中就直接返回缓存的内容。
4.判断熔断器是否打开,如果开启,则跳到第8步。
5.判断线程池/队列/信号量是否已满,如果已满,则跳到第8步。
6.执行HystrixObservableCommand.construct()/HystrixCommand.run(),如果执行失败或超时,跳到第8步;否则,跳到第9步;
7.统计熔断器监控指标。
8.走Fallback备用逻辑。
9.返回成功的响应。

此外第5步线程池/队列/信号量已满时,还会执行第7步逻辑,更新熔断器统计信息,而第6步无论成功与否,都会更新熔断器统计信息。

 

详细说明

1.构建一个HystrixCommand或者HystrixObservableCommand对象,将请求包装到Command对象中。

// 创建HystrixCommand对象
HystrixCommand command = new HystrixCommand(arg1, arg2);

// 创建HystrixObservableCommand
HystrixObservableCommand command = new HystrixObservableCommand(arg1, arg2);


2.执行命令。

// 调用后直接block住,属于同步调用,直到依赖服务返回单条结果,或者抛出异常,此方法(只适用于HystrixCommand)
K value = command.execute();

// 返回一个Future,属于异步调用,可以通过Future.get()获取单条结果,此方法(只适用于HystrixCommand)
Future<K> fValue = command.queue();

// 订阅一个Observable对象,Observable代表的是依赖服务返回的结果,获取到一个那个代表结果的Observable对象的拷贝对象
Observable<K> ohValue = command.observe();

// 返回一个Observable对象,如果我们订阅这个对象,就会执行command并且获取返回结果
Observable<K> ocValue = command.toObservable();


3.判断当前请求是否有缓存,如果在缓存中就直接返回缓存的内容。

如果此命令启用了请求缓存,并且对请求的响应在缓存中可用,则该缓存的响应将以Observable的形式立即返回。


4.判断熔断器是否打开,如果开启,则跳到第8步。

判断断路器是否处于打开的状态,如果是打开状态,那么Hystrix就不再会去执行命令,直接跳到第 8 步,获取 fallback 方法,执行 fallback 逻辑。


5.判断线程池/队列/信号量是否已满,如果已满,则跳到第8步。

判断command对应的线程池/队列/信号量是否已满,如果已经满了,那么Hystrix就不再会去执行命令,直接跳到第 8 步,获取 fallback 方法,执行 fallback 逻辑。


6.执行HystrixObservableCommand.construct()/HystrixCommand.run(),如果执行失败或超时,跳到第8步;否则,跳到第9步;

调用HystrixObservableCommand.construct()或HystrixCommand.run()来实际执行这个command。

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

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

如果执行失败或超时,那么command所在的线程就会抛出异常,直接跳到第 8 步,获取 fallback 方法,执行 fallback 逻辑。

7.统计熔断器监控指标。

Hystrix向断路器报告成功,失败,拒绝和超时,断路器保持滚动的一组计算统计信息的计数器。

它使用这些统计信息来确定电路何时应“跳闸”,在此点它会将随后的所有请求短路,直到经过恢复期为止,在此之后,在首先检查某些运行状况检查之后,它将再次闭合电路。


8.走Fallback备用逻辑。

Hystrix在以下几种情况下会走降级逻辑:

1.执行construct()或run()抛出异常
2.熔断器打开导致命令短路
3.命令的线程池和队列或信号量的容量超额,命令被拒绝
4.命令执行超时

降级回退方式:

1.Fail Fast 快速失败:快速失败是最普通的命令执行方法,命令没有重写降级逻辑。 如果命令执行发生任何类型的故障,它将直接抛出异常。
2.Fail Silent 无声失败:指在降级方法中通过返回null,空Map,空List或其他类似的响应来完成。
3.Fallback: Static 返回默认值:指在降级方法中返回静态默认值。 这不会导致服务以“无声失败”的方式被删除,而是导致默认行为发生。
4.Fallback: Stubbed 自己组装一个值返回:当命令返回一个包含多个字段的复合对象时,适合以Stubbed 的方式回退。
5.Fallback: Cache via Network 利用远程缓存:有时,如果调用依赖服务失败,可以从缓存服务(如redis)中查询旧数据版本。由于又会发起远程调用,所以建议重新封装一个Command,使用不同的ThreadPoolKey,与主线程池进行隔离。
6.Primary + Secondary with Fallback 主次方式回退:有时系统具有两种行为- 主要和次要,或主要和故障转移。主要和次要逻辑涉及到不同的网络调用和业务逻辑,所以需要将主次逻辑封装在不同的Command中,使用线程池进行隔离。为了实现主从逻辑切换,可以将主次command封装在外观HystrixCommand的run方法中,并结合配置中心设置的开关切换主从逻辑。由于主次逻辑都是经过线程池隔离的HystrixCommand,因此外观HystrixCommand可以使用信号量隔离,而没有必要使用线程池隔离引入不必要的开销。


9.返回成功的响应。

返回结果。

 

熔断器工作原理

(图来源:https://github.com/Netflix/Hystrix/wiki/How-it-Works

说明:

第一步,调用allowRequest()判断是否允许将请求提交到线程池

1.如果熔断器强制打开,circuitBreaker.forceOpen为true,不允许放行,返回。
2.如果熔断器强制关闭,circuitBreaker.forceClosed为true,允许放行。此外不必关注熔断器实际状态,也就是说熔断器仍然会维护统计数据和开关状态,只是不生效而已。

第二步,调用isOpen()判断熔断器开关是否打开

1.如果熔断器开关打开,进入第三步,否则继续;
2.如果一个周期内总的请求数小于circuitBreaker.requestVolumeThreshold的值,允许请求放行,否则继续;
3.如果一个周期内错误率小于circuitBreaker.errorThresholdPercentage的值,允许请求放行。否则,打开熔断器开关,进入第三步。


第三步,调用allowSingleTest()判断是否允许单个请求通行,检查依赖服务是否恢复

如果熔断器打开,且距离熔断器打开的时间或上一次试探请求放行的时间超过circuitBreaker.sleepWindowInMilliseconds的值时,熔断器器进入半开状态,允许放行一个试探请求;否则,不允许放行。


此外,为了提供决策依据,每个熔断器默认维护了10个bucket,每秒一个bucket,当新的bucket被创建时,最旧的bucket会被抛弃。其中每个blucket维护了请求成功、失败、超时、拒绝的计数器,Hystrix负责收集并统计这些计数器。

 

 

 

参考资料:

https://github.com/Netflix/Hystrix/wiki

https://my.oschina.net/7001/blog/1619842

https://blog.csdn.net/heimabb/article/details/80353362

https://my.oschina.net/wangxindong/blog/1518994

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值