一、什么是 Hystrix?
??在分布式环境中,许多服务依赖项中的一些不可避免地会失败。Hystrix 是一个库,它通过添加延迟容错和容错逻辑来帮助您控制这些分布式服务之间的交互。Hystrix 通过隔离服务之间的访问点、停止它们之间的级联故障并提供回退选项来做到这一点,所有这些都可以提高系统的整体弹性。
二、Hystrix 有什么用?
Hystrix 旨在执行以下操作:
- 通过第三方客户端库访问(通常通过网络)依赖关系,保护和控制延迟和故障。
- 停止复杂分布式系统中的级联故障。
- 快速失败并迅速恢复。
- 尽可能回退并优雅降级。
- 实现近乎实时的监控、警报和操作控制。
三、Hystrix 解决了什么问题?
??复杂分布式架构中的应用程序有几十个依赖项,每个依赖项都不可避免地会在某些时候失败。如果主机应用程序没有与这些外部故障隔离开来,它就有被它们一起关闭的风险。 例如,对于依赖于 30 个服务且每个服务的正常运行时间为 99.99% 的应用程序,您可以期待以下内容:
99.99 30 = 99.7% 的正常运行时间 10 亿次请求的 0.3% = 3,000,000 次故障 2 小时以上的停机时 间/月,即使所有依赖项都具有出色的正常运行时间。
现实通常更糟。
即使所有依赖项都表现良好,如果您不对整个系统进行弹性设计,即使对数十项服务中的每项服务造成 0.01% 的停机时间的总影响也相当于可能每月停机数小时。
正常的应用访问链
当部分服务不可用时,可能造成雪崩
??在大流量的情况下,单个后端依赖变得潜在可能会导致所有服务器上的所有资源在几秒钟内变得饱和。
??应用程序中通过网络或进入可能导致网络请求的客户端库的每个点都是潜在故障的根源。比故障更糟糕 的是,这些应用程序还可能导致服务之间的延迟增加,这会备份队列、线程和其他系统资源,从而导致 整个系统出现更多的级联故障。 ??当通过第三方客户端执行网络访问时,这些问题会更加严重——一个“黑匣子”,其中实现细节被隐藏并 且可以随时更改,并且每个客户端库的网络或资源配置都不同,并且通常难以监控和改变。
??更糟糕的是传递依赖,它们执行潜在的昂贵或容易出错的网络调用,而没有被应用程序显式调用。
??网络连接失败或降级、服务和服务器出现故障或变慢、新的库或服务部署会改变行为或性能特征都会导 致客户端出现错误。
??所有这些都代表了需要隔离和管理的故障和延迟,以便单个故障依赖项无法关闭整个应用程序或系统。
四、Hystrix 的设计原则是什么?
Hystrix 通过以下方式工作:
- 防止任何单个依赖项用完所有容器(例如 Tomcat)用户线程。
- 减轻负载并快速失败,而不是排队。
- 在可行的情况下提供回退,以保护用户免于失败。
- 使用隔离技术(例如隔板、泳道和断路器模式)来限制任何一种依赖项的影响。
- 通过近乎实时的指标、监控和警报优化发现时间
- 通过配置更改的低延迟传播和对 Hystrix 大部分方面的动态属性更改的支持来优化恢复时间,这允许您使用低延迟反馈循环进行实时操作修改。
- 防止在整个依赖客户端执行中出现故障,而不仅仅是在网络流量中。
五、Hystrix 如何实现其目标?
Hystrix 通过以下方式做到这一点:
- 将对外部系统(或“依赖项”)的所有调用包装在一个HystrixCommand或HystrixObservableCommand对象中,该对象通常在单独的线程中执行(这是命令模式的一个示例)。
- 超时调用时间超过您定义的阈值。有一个默认值,但是对于大多数依赖项,您可以通过“属性”自定义设置这些超时,以便它们略高于每个依赖项测量的 99.5 %性能。
- 为每个依赖项维护一个小型线程池(或信号量);如果它已满,发往该依赖项的请求将立即被拒绝而不是排队。
测量成功、失败(客户端抛出的异常)、超时和线程拒绝。 - 如果服务的错误百分比超过阈值,则手动或自动触发断路器以在一段时间内停止对特定服务的所有请求。
- 当请求失败、被拒绝、超时或短路时执行回退逻辑。
- 近乎实时地监控指标和配置更改。
当您使用 Hystrix 包装每个底层依赖项时,如上图所示的架构将更改为类似于下图。每个依赖项相互隔离,限制在发生延迟时它可以饱和的资源,并包含在回退逻辑中,该逻辑决定当依赖项中发生任何类型的故障时做出什么响应:
六、实践配置
application.yml
feign:
hystrix:
enabled: true
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
hystrix:
command:
default:
requestLogEnabled: true
execution:
timeout:
enabled: true
isolation:
较少。
strategy: THREAD
thread:
timeoutInMilliseconds: 5000
interruptOnTimeout: true
interruptOnCancel: false
circuitBreaker:
就不要引入Hystrix。
enabled: true
超出了时间窗口内的总请求数,则熔断永远也不会被触发
requestVolumeThreshold: 20
打开后,Hystrix会在经过一段时间后就放行一条请求
执行失败,则认为服务仍然不可用,熔断器保持打开。
为5秒。
sleepWindowInMilliseconds: 5000
配置来判断是否需要打开熔断器
快速失败掉
errorThresholdPercentage: 50
forceOpen: false
forceClosed: false
metrics:
rollingStats:
即一个滑动窗口默认统计的是10秒内的请求数据。
timeInMilliseconds: 10000
metrics.rollingStats.numBuckets == 0必须成立,否则就会抛出异常
numBuckets: 10
rollingPercentile:
统计图表。
enabled: true
timeInMilliseconds: 60000
metrics.rollingPercentile.numBuckets == 0必须成立,否则会抛出异常
numBuckets: 6
保存到桶内。
bucketSize: 100
healthSnapshot:
秒。
metrics.healthSnapshot.intervalInMilliseconds计算出桶数。
intervalInMilliseconds: 500
threadpool:
default:
coreSize: 1
allowMaximumSizeToDivergeFromCoreSize: false
allowMaximumSizeToDivergeFromCoreSize
maximumSize: 10
Hystrix不会向队列内存放作业。
在核心线程池都忙碌的情况下,会将作业暂时存放在此队列内,但是超出此队列的请求依然会被拒绝
maxQueueSize: -1
queueSizeRejectionThreshold: 5
keepAliveTimeMinutes: 1
Hystrix监控
dashboard
工作原理
执行流程图
对应源码:
ribbon:
MaxAutoRetries: 1
MaxAutoRetriesNextServer: 1
OkToRetryOnAllOperations: true
ServerListRefreshInterval: 2000
ConnectTimeout: 6000
ReadTimeout: 6000
七、工作原理
执行流程图 对应源码: AbstractCommand.Class
(Hystrix的统计采用滑动窗口的方式进行统计,将1s拆成10个桶,可以统计滑动窗口内的1s中的数据)
电路开闭发生的具体方式如下:
- 判断固定窗口内的请求数满足某个阈值 (
HystrixCommandProperties.circuitBreakerRequestVolumeThreshold() ). - 并假设错误百分比超过阈值错误百分比
( HystrixCommandProperties.circuitBreakerErrorThresholdPercentage() ) - 然后断路器从 转变 CLOSED 为 OPEN 。
- 当它打开时,它会将针对该断路器的所有请求短路。
- 一段时间后( HystrixCommandProperties.circuitBreakerSleepWindowInMilliseconds() ),下一个请
求被允许通过(这是 HALF-OPEN 状态)。如果请求失败,断路器将 OPEN 在睡眠窗口期间返回状 态。如果请求成功,断路器转换到1. CLOSED 中的逻辑再次接管
八、参考文档
??Hystrix:分布式系统的延迟和容错
|