【Hystrix技术指南】(4)故障切换的运作流程

简介: 【Hystrix技术指南】(4)故障切换的运作流程

[温馨提示]


承接上一篇文章🏹【Hystrix技术指南】(3)超时机制的原理和实现





[背景介绍]


  • 分布式系统的规模和复杂度不断增加,随着而来的是对分布式系统可用性的要求越来越高。在各种高可用设计模式中,【熔断、隔离、降级、限流】是经常被使用的。而相关的技术,Hystrix本身早已算不上什么新技术,但它却是最经典的技术体系!。
  • Hystrix以实现熔断降级的设计,从而提高了系统的可用性。
  • Hystrix是一个在调用端上,实现断路器模式,以及隔舱模式,通过避免级联故障,提高系统容错能力,从而实现高可用设计的一个Java服务组件库。
  • Hystrix实现了资源隔离机制



背景介绍


目前对于一些非核心操作,如增减库存后保存操作日志发送异步消息时(具体业务流程),一旦出现MQ服务异常时,会导致接口响应超时,因此可以考虑对非核心操作引入服务降级、服务隔离。



Hystrix说明


官方文档

Hystrix是Netflix开源的一个容灾框架,解决当外部依赖故障时拖垮业务系统、甚至引起雪崩的问题。



为什么需要Hystrix?


  • 在大中型分布式系统中,通常系统很多依赖(HTTP,hession,Netty,Dubbo等),在高并发访问下,这些依赖的稳定性与否对系统的影响非常大,但是依赖有很多不可控问题:如网络连接缓慢,资源繁忙,暂时不可用,服务脱机等。


  • 当依赖阻塞时,大多数服务器的线程池就出现阻塞(BLOCK),影响整个线上服务的稳定性,在复杂的分布式架构的应用程序有很多的依赖,都会不可避免地在某些时候失败。高并发的依赖失败时如果没有隔离措施,当前应用服务就有被拖垮的风险。



例如:一个依赖30个SOA服务的系统,每个服务99.99%可用。
99.99%的30次方 ≈ 99.7%
0.3% 意味着一亿次请求 会有 3,000,00次失败
换算成时间大约每月有2个小时服务不稳定.
随着服务依赖数量的变多,服务不稳定的概率会成指数性提高.
解决问题方案:对依赖做隔离。
复制代码



Hystrix设计理念


想要知道如何使用,必须先明白其核心设计理念,Hystrix基于命令模式,通过UML图先直观的认识一下这一设计模式

image.png

  • 可见,Command是在ReceiverInvoker之间添加的中间层,Command实现了对Receiver的封装


  • API既可以是Invoker又可以是reciever,通过继承Hystrix核心类HystrixCommand来封装这些API(例如,远程接口调用,数据库查询之类可能会产生延时的操作)


  • 就可以为API提供弹性保护了。



Hystrix如何解决依赖隔离


  1. Hystrix使用命令模式HystrixCommand(Command)包装依赖调用逻辑,每个命令在单独线程中/信号授权下执行。


  1. 可配置依赖调用超时时间,超时时间一般设为比99.5%平均时间略高即可。当调用超时时,直接返回或执行fallback逻辑。


  1. 为每个依赖提供一个小的线程池(或信号),如果线程池已满调用将被立即拒绝,默认不采用排队,加速失败判定时间。


  1. 依赖调用结果分,成功,失败(抛出异常),超时,线程拒绝,短路。 请求失败(异常,拒绝,超时,短路)时执行fallback(降级)逻辑。


  1. 提供熔断器组件,可以自动运行或手动调用,停止当前依赖一段时间(10秒),熔断器默认错误率阈值为50%,超过将自动运行


  1. 提供近实时依赖的统计和监控




Hystrix流程结构解析

image.png



流程说明:


  1. 每次调用构建HystrixCommand或者HystrixObservableCommand对象,把依赖调用封装在run()方法中.


  1. 结果是否有缓存如果没有执行execute()/queue做sync或async调用,对应真正的run()/construct()


  1. 判断熔断器(circuit-breaker)是否打开,如果打开跳到步骤8,进行降级策略,如果关闭进入步骤.


  1. 判断线程池/队列/信号量是否跑满,如果跑满进入降级步骤8,否则继续后续步骤.


  1. 使用HystrixObservableCommand.construct()还是HystrixCommand.run(),运行依赖逻辑


  1. 依赖逻辑调用超时,进入步骤8


  1. 判断逻辑是否调用成功


  • 6a 返回成功调用结果
  • 6b 调用出错,进入步骤8.



8.计算熔断器状态,所有的运行状态(成功, 失败, 拒绝,超时)上报给熔断器,用于统计从而判断熔断器状态.


9.getFallback()降级逻辑. a. 没有实现getFallback的Command将直接抛出异常


b. fallback降级逻辑调用成功直接返回

c. 降级逻辑调用失败抛出异常


10.返回执行成功结果


以下四种情况将触发getFallback调用:


  1. run()方法抛出非HystrixBadRequestException异常


  1. run()方法调用超时


  1. 熔断器开启短路调用


  1. 线程池/队列/信号量是否跑满


熔断器:Circuit Breaker


每个熔断器默认维护10个bucket,每秒一个bucket,每个bucket记录成功,失败,超时,拒绝的状态,默认错误超过50%且10秒内超过20个请求进行中断短路。


image.png



Hystrix隔离分析


Hystrix隔离方式采用线程/信号的方式,通过隔离限制依赖的并发量和阻塞扩散.


线程隔离


  • 执行依赖代码的线程与请求线程(如:jetty线程)分离,请求线程可以自由控制离开的时间(异步过程)。


  • 通过线程池大小可以控制并发量,当线程池饱和时可以提前拒绝服务,防止依赖问题扩散。


  • 线上建议线程池不要设置过大,否则大量堵塞线程有可能会拖慢服务器。




实际案例:


Netflix公司内部认为线程隔离开销足够小,不会造成重大的成本或性能的影响。Netflix 内部API 每天100亿的HystrixCommand依赖请求使用线程隔,每个应用大约40多个线程池,每个线程池大约5-20个线程。




信号隔离


信号隔离也可以用于限制并发访问,防止阻塞扩散, 与线程隔离最大不同在于执行依赖代码的线程依然是请求线程(该线程需要通过信号申请),如果客户端是可信的且可以快速返回,可以使用信号隔离替换线程隔离,降低开销。


信号量的大小可以动态调整, 线程池大小不可以。



线程隔离与信号隔离区别如下图:

image.png





相关文章
|
7月前
|
缓存 Java 应用服务中间件
Hystrix中RequestCache请求缓存技术
Hystrix中RequestCache请求缓存技术
68 0
|
7月前
|
缓存 Java 应用服务中间件
Hystrix线程池技术实现资源隔离
Hystrix线程池技术实现资源隔离
23 0
|
设计模式 缓存 监控
【Hystrix技术指南】(7)故障切换的运作流程原理分析(含源码)
【Hystrix技术指南】(7)故障切换的运作流程原理分析(含源码)
223 0
【Hystrix技术指南】(7)故障切换的运作流程原理分析(含源码)
|
设计模式 缓存 安全
【Hystrix技术指南】(6)请求合并机制原理分析
【Hystrix技术指南】(6)请求合并机制原理分析
159 0
【Hystrix技术指南】(6)请求合并机制原理分析
|
数据采集 缓存 监控
【Hystrix技术指南】(5)Command创建和执行实现
【Hystrix技术指南】(5)Command创建和执行实现
158 0
【Hystrix技术指南】(5)Command创建和执行实现
|
设计模式 Java 数据中心
【Hystrix技术指南】(3)超时机制的原理和实现
【Hystrix技术指南】(3)超时机制的原理和实现
204 0
|
设计模式 缓存 Java
【Hystrix技术指南】(2)参数配置的详细介绍
【Hystrix技术指南】(2)参数配置的详细介绍
132 0
|
5月前
|
缓存 运维 监控
微服务技术系列教程(22) - SpringCloud- 服务保护机制Hystrix
微服务技术系列教程(22) - SpringCloud- 服务保护机制Hystrix
60 0
|
6月前
|
缓存 监控 Java
12SpringCloud - 断路器(Hystrix)引入
12SpringCloud - 断路器(Hystrix)引入
29 0
|
6月前
|
Java 微服务 Spring
Spring Cloud Hystrix简单实用
Spring Cloud Hystrix简单实用
59 0