什么是Hystrix?
在分布式环境中,不可避免地会有许多服务依赖项失败。Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助您控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止跨服务的级联故障并提供回退选项来实现这一点,所有这些都可以提高系统的总体弹性。
Hystrix的历史
Hystrix是从Netflix API团队2011年开始的弹性工程工作中发展而来的。2012年,Hystrix继续发展和成熟,Netflix的许多团队都采用了它。如今,Netflix每天通过Hystrix执行数百亿个线程隔离调用和数千亿个信号量隔离调用。这在正常运行时间和恢复力方面带来了显著的改善。
Hystrix是干什么用的?
Hystrix被设计用来做如下事宜:
- 保护和控制通过第三方客户端库访问的依赖(通常是通过网络)的延迟和失败。
- 停止复杂分布式系统中的级联故障。
- 快速熔断和迅速恢复
- 回退并尽可能优雅地降级。
- 启用近实时监视、警报和操作控制。
Hystrix解决了什么问题?
复杂分布式体系结构中的应用程序有许多依赖项,每个依赖项都不可避免地会在某个时候失败。如果主机应用程序不能与这些外部故障隔离,则有可能随这些故障一起停机。
例如,对于一个依赖于30个服务的应用程序,其中每个服务有99.99%的正常运行时间,以下是您可以预期的情况:
99.9930 = 99.7%正常运行时间
10亿请求中的0.3% = 300万次失败
2+小时停机/月,即使所有依赖有优秀的正常运行时间。
现实通常更糟。
即使在所有依赖项都表现良好的情况下,如果您不为弹性设计整个系统,那么即使0.01%的停机时间对几十个服务中的每一个服务的总体影响也相当于每月潜在的停机时间数小时。
当一切正常时,请求流可以是这样的:
当许多后端系统之一成为潜在的,它可以阻止整个用户的请求:
在高流量的情况下,单个后端依赖项的潜在影响可能会导致所有服务器上的所有资源在几秒钟内饱和。
应用程序中通过网络或进入客户端库可能导致网络请求的每一点都是潜在故障的根源。比故障更糟糕的是,这些应用程序还会导致服务之间的延迟增加,从而备份队列、线程和其他系统资源,从而在整个系统中导致更多的级联故障。
当通过第三方客户端执行网络访问时,这些问题会更加严重——这是一个“黑盒”,其中隐藏了实现细节,可以在任何时候更改,并且每个客户端库的网络或资源配置不同,通常很难监控和更改。
更糟糕的是,传递依赖项在不被应用程序显式调用的情况下执行潜在的昂贵或容易出错的网络调用。
网络连接失败或降级。服务和服务器失败或变慢。新的库或服务部署会改变行为或性能特征。客户端库有bug。
所有这些都表示需要隔离和管理的失败和延迟,这样单个失败依赖项就不能破坏整个应用程序或系统。
Hystrix的设计原则是什么?
- 防止任何单个依赖项耗尽所有容器(如Tomcat)用户线程。
- 减少负载和快速失败,而不是排队。
- 在可行的情况下提供回退,以保护用户避免失败。
- 使用隔离技术(如舱壁、泳道和断路器模式)来限制任何依赖项的影响。
- 通过接近实时的度量、监视和警报优化发现时间
- 通过配置更改的低延迟传播和对Hystrix大多数方面的动态属性更改的支持来优化恢复时间,这允许您使用低延迟反馈循环进行实时操作修改。
- 保护整个依赖客户端执行中的失败,而不仅仅是在网络流量中。
Hystrix是如何实现其目标的?
- 将对外部系统(或“依赖项”)的所有调用包装在HystrixCommand或HystrixObservableCommand对象中,该对象通常在单独的线程中执行(这是命令模式的一个示例)。
- 超时调用的时间长于您定义的阈值。有一个默认值,但是对于大多数依赖项,您可以通过“属性”自定义设置这些超时,以便它们比每个依赖项的99.5%的性能略高。
- 为每个依赖项维护一个小的线程池(或信号量);如果它已经满了,针对该依赖项的请求将立即被拒绝,而不是排队。
- 度量成功、失败(客户端抛出的异常)、超时和线程拒绝。
- 断开断路器,以在一段时间内停止对特定服务的所有请求,如果服务的错误百分比超过阈值,则手动或自动停止。
- 在请求失败、被拒绝、超时或短路时执行回退逻辑。
- 几乎实时地监视度量和配置更改。
当您使用Hystrix包装每个底层依赖项时,上面图表中所示的体系结构将发生变化,类似于下面的图表。每个依赖项都是相互隔离的,当延迟发生时,依赖项所占用的资源受到限制,并且在决定当依赖项中发生任何类型的故障时应作出何种响应的回退逻辑中进行了介绍: