Spring Cloud 组件原理系列(二)Hystrix篇

1. Hystrix 简介

Hystrix 是 Netflix 开源的一款容错系统,能帮助使用者码出具备强大的容错能力和鲁棒性的程序。Hystrix 具备拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包(request collapsing,即自动批处理,译者注),以及监控和配置等功能。

Hystrix 源于 Netflix API 团队在 2011 年启动的弹性工程工作,而目前它在 Netflix 每天处理着数百亿的隔离线程以及数千亿的隔离信号调用。Hystrix 是基于 Apache License 2.0 协议的开源的程序库,目前托管在 GitHub 上。

为什么用Hystrix?什么情况下用?

分布式系统中,或者说微服务,各个系统错综复杂,一个系统依赖的服务比较多,而且会有多级依赖。当其中某一个服务出现问题,在高并发的情况下都有可能导致整个系统的瘫痪,蝴蝶效应在这里表现明显。

也许你会问为什么会这样?如上图,假如服务I出现较严重延迟,这时上层应用访问量tps比较大时, 首先上层应用资源会被占满,并且一般网络请求(http/rpc)都有重试机制,服务I的压力会更大,严重时则会导致应用宕机。

d6f9ad10-fea7-11e7-806c-257f5e05f705.jpg

2. Hystrix 设计理念

在复杂的分布式系统中通常有很多依赖,如果一个应用不能对来自依赖故障进行隔离,那么应用本身就处于被拖垮的风险中。在一个高流量的网站中,某一个单一后端一旦发生延迟,将会在数秒内导致所有的应用资源被耗尽,这也就是我们常说的雪崩效应。

比如在电商系统的下单业务中,在订单服务创建订单后同步调用库存服务进行库存的扣减,假如库存服务出现了故障,那么会导致下单请求线程会被阻塞,当有大量的下单请求时,则会占满应用连接数从而导致订单服务无法对外提供服务。

容错设计的理念

  • 凡是依赖都有可能会失败。
  • 凡是资源都有限制,比如 CPU、Memory、Threads、Queue。
  • 网络并不可靠,可能存在网络抖动等其他问题。
  • 延迟是应用稳定的杀手,延迟会占据大量的资源。

容错限流的手段

  • 限流:限制最大并发数。
  • 熔断:错误数达到阈值时,类似于保险丝熔断。
  • 隔离:隔离不同的依赖调用。
  • 服务降级:资源不足时进行服务降级。
  • 主动超时:在调用依赖时尽快的超时,可以设置比较短的超时时间,防止长时间的等待。

3. Hystrix 核心概念

Hystrix是Netflix公司开源的一款容错框架。 它可以完成以下几件事情:

  • 熔断器:当请求失败率达到一定的阈值时,会打开断路器开关,直接拒绝后续的请求,并且具有弹性机制,在后端服务恢复后,会自动关闭断路器开关。
  • 资源隔离:包括线程池隔离和信号量隔离,避免某个依赖出现问题会影响到其他依赖。
  • 降级回退:当断路器开关被打开,服务调用超时/异常,或者资源不足(线程、信号量)会进入指定的fallback降级方法。
  • 请求合并:可以实现将一段时间内的请求合并,然后只对后端服务发送一次请求。
  • 请求结果缓存:hystrix实现了一个内部缓存机制,可以将请求结果进行缓存,那么对于相同的请求则会直接走缓存而不用请求后端服务。

3.1. 熔断器

断路器工作原理如下:

2591074-4188ce088305a4e5.webp

Hystrix 是基于滚筒式来处理,每一秒会产生一个 buckets,每产生一个新的 buckets 就会移除一个最老的 buckets,默认是 10 秒一个窗口。buckets 在内存中就是一种数据结构,每个 buckets 会记录 Metrics 的相关数据,比如 成功、失败、超时、拒绝。

当一个 HystrixCommand 进来后,会先通过 allowRequest() 方法判断是否允许通过该次请求,allowRequest() 方法会通过 isOpen 判断断路器是否打开。断路器关闭,则允许通过该次请求;断路器打开,则会判断是否过了睡眠周期。没有过睡眠周期则返回 false,拒绝通过该次请求,过了睡眠周期则会尝试放行。

isOpen() 方法会按照 (failure) / (success+failure) 公式计算出失败率,如果失败率大于阈值,则会触发熔断。公式中的成功、失败的数据就来源于每10秒中一个窗口的滚筒数据。对于一个依赖调用,要么调用成功,要么调用失败(包括异常、超时、拒绝),这些调用结果都会记录到 buckets 中。对于调用成功结果来说,还会判断断路器开关是否打开,如果是打开状态的话,则会关闭断路器并重置相关的计数器。

线路的开路闭路详细逻辑如下:

  1. 假设线路内的容量(请求QPS)达到一定阈值(通过HystrixCommandProperties.circuitBreakerRequestVolumeThreshold()配置)
  2. 同时,假设线路内的错误率达到一定阈值(通过HystrixCommandProperties.circuitBreakerErrorThresholdPercentage()配置)
  3. 熔断器将从『闭路』转换成『开路』
  4. 若此时是『开路』状态,熔断器将短路后续所有经过该熔断器的请求,这些请求直接走『失败回退逻辑』
  5. 经过一定时间(即『休眠窗口』,通过HystrixCommandProperties.circuitBreakerSleepWindowInMilliseconds()配置),后续第一个请求将会被允许通过熔断器(此时熔断器处于『半开』状态),若该请求失败,熔断器将又进入『开路』状态,且在休眠窗口内保持此状态;若该请求成功,熔断器将进入『闭路』状态,回到逻辑1循环往复。

3.2. 资源隔离

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值