什么是熔断器
熔断器,原本是电路中在电器发生短路时的防止电路过载的开关装置,它切断发生短路的电路,从而防止因电路过载导致的发热起火等灾难的发生。同样的,在为服务中也可能出现类似电路中短路的事故发生,所以为了防止类似的灾难的发生,Hystrix(微服中的熔断器)为此而被设计出来。
官方的定义
以下是官方对hystrix的定义:
In a distributed environment, inevitably some of the many service dependencies will fail. Hystrix is a library that helps you control the interactions between these distributed services by adding latency tolerance and fault tolerance logic. Hystrix does this by isolating points of access between the services, stopping cascading failures across them, and providing fallback options, all of which improve your system’s overall resiliency.
以下是我的翻译:
在分布式环境中,服务之间的调用不可避免地会失败(网络原因、服务器异常等 )。Hystrix是一个在分布式环境中通过增加延迟性和容错来帮助你控制这些服务之间的交互。Hystrix是通过隔离服务之间的访问,阻止服务间的连锁故障,并提供可选项配置,所有这些旨在提高您微服系统的整体弹性。
(以上仅表示我个人的翻译,如果有高见欢迎评论)
Hystrix的历史
Hystrix是由Netflix Api团队的一个开始于2011年提高服务弹性的项目演变而来的,在2012年Hystrix不断的发展和成熟,在Netflix团队中也有越来越多的项目使用到Hystrix.如今,在Netflix每天有成千上万的线程分离和数百亿的信号分离的调用是通过Hystrix完成的。也因此系统的正常运行时间和弹性得到了显著的提高。
Hystrix被设计用来做什么?
- 提供保护和控制过度的延迟和依赖失败。
- 在复杂的分布式系统中防止级联失败。
- 使失败快速结束和快速恢复(Fail fast and rapidly recover)。
- 回退和尽可能优雅的降级。
- 提供短近乎实时的监控、警报和操作控制。
Hystrix可以解决什么问题?
在官方文档的介绍中举了一个这样的例子,假设一个应用依赖30个微服务,并且这30个微服的正常运行时间高达99.99%(这对于一个微服来说表现已经很不错了)。这样的情况下,我们能得到这样的结论:
- 99.99的30次方 = 99.7% 正常运行时间
- 如果有10亿次请求则有3,000,000次的失败请求
- 即使所依赖的30个服务都表现很棒,每个月还是有2小时的停机时间
这是在我们假设的依赖的服务表现很棒的情况下,还是会有每月2小时的宕机,在实际的生产环境中情况肯定要比这个更糟糕,尤其对于一些金融或是对服务稳定要求较高的行业,这样的情况是不能允许的。由此可见Hystrix在微服中的重要作用。
如果所有的服务时健康的那么请求的流程如下图:
在流程图中一个关于用户的请求依赖A H I P四个服务,如果这4个服务中有个服务请求超时了,那么这将会导致整个用户请求的阻塞,如果在一秒内有50个以上的这样的请求执行,那么以为意味着会有50个以上的请求在这秒时阻塞的,这将消耗大量的线程。如下图所示:
对于高访问量的服务来说,这个问题会导致,服务的资源在短时间内被耗尽。
当涉及到与第三方后台进行交互时,这些情况会变得更加糟糕。
网络连接失败或降级、服务的失败或变慢、配置或是性能的优化导致的服务的重新部署、客服端库的bug,所有的这些失败或是延迟的问题都需要被隔离和管理从而防止因某个单一的错误拖垮整个微服系统。
Hystrix是依据怎样的设计原则?
- 防止微服中某个单一服务,消耗掉容器(如 tomcat)的所有用户线程。
- 减少负载和快速失败而不是排队。
- 采用隔离技术(如bulkhead, swimlane,和断路器模式)来限制任何一个依赖性的影响。
- 通过实时指标、监视和警报来优化发现时间。
- 在打多算方面支持动态特性改变和配置变化的低延迟传播从而达到优化回复时间的目的,所以Hytrix允许您以低延迟反馈循环进行实时操作修改.
- 保护整个依赖客户端执行中的失败,而不仅仅是在网络流量中。
Hystrix是如何实现这些目标的?
- Hystrix 在 HystrixCommand 和 HystrixObservableCommand类 中包装所有的对依赖服务的调用,这些调用通常在一个单独线程中执行。(Hystrix在这用的是“命令模式”的设计模式)
- 调用时间超过我们设置的超时时间才会被认定为超时,当然超时时间有默认值,但是对于大多数依赖项,您可以通过“属性”来自定义这些超时值,以使它们比每个依赖项的实测99.5%百分点性能略高。
- 为每个依赖维护一个小的线程池(或信号量);
如果它变满了,发往这个依赖关系的请求将被立即拒绝而不是排队。 - 衡量成功,失败(客户端抛出的异常),超时和线程拒绝。
- 跳闸断路器可以在一段时间内停止对特定服务的所有请求,无论是手动还是自动,如果服务的错误百分比超过阈值。
- 当请求失败被拒绝、超时或短路时执行备用逻辑。
- 近乎实时的监控指标和配置的更改。
如下如图调用外部的依赖服务必须通过包装的command,然后通过command实现真正的调用。
Hystrix工作的流程
下图显示了通过Hystrix向依赖服务发出请求的流程
总结
这篇文章其实大部分是依据官方文档对Hystrix的介绍来写的,当中有我个人的理解,也可以把它作为官方介绍的中文版翻译来看。文章中如有错误的地方欢迎留言,如果觉得这篇文章对您有用,欢迎点赞。
参考
Hystrix官方文档介绍 https://github.com/Netflix/Hystrix/wiki