Hystrix 容错处理

Posted 码道简记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hystrix 容错处理相关的知识,希望对你有一定的参考价值。


一、问题

    假设单块应用的可用性是 99.99%,如果被拆分为30个微服务后,总体的可用性是多少?

   答案是 99.7%,每月2小时宕机时间,实际情况可能更长,30个微服务可用性算法是 99.99%的30阶乘(30个99.99%相乘)。


二、基本的容错模式

  1. 集群容错某一个服务构建多个实例,当一个服务实例出现问题时重试其他实例。针对不同的重试方式可使用不同的集群容错策略,常见的包括 Failover(失效转移)、Failback(失败通知)、Failsafe(失败安全)和 Failfast(快速失败)等。

  2. 主动超时:Http请求主动设置一个超时时间,超时就直接返回,不会造成服务堆积

  3. 限流:限制最大并发数

  4. 熔断:当错误数超过阈值时快速失败,不调用后端服务,同时隔一定时间放几个请求去重试后端服务是否能正常调用,如果成功则关闭熔断状态,失败则继续快速失败,直接返回。(此处有个重试,重试就是弹性恢复的能力)

  5. 隔离:把每个依赖或调用的服务都隔离开来,防止级联失败引起整体服务不可用。

     一个案例就是一些社交平台将名人的自媒体流量全部路由到服务的核心池子中,而将普通用的流量路由到另外一个服务池子中,有效隔离了普通用户和重要用户的负载。

  6. 降级:服务失败或异常后,返回指定的默认信息


三、容错理念

  1. 凡是依赖都可能会失败

  2. 凡是资源都有限制(CPU、内存、线程池)

  3. 网络并不靠谱

  4. 延迟是应用稳定性最大杀手(可能由于延迟最终拖垮整个微服务,给服务设置一个超时时间来解决延迟引起的问题)


四、Hystrix 容错的流程图

    Hystrix是一个延迟和容错库,旨在隔离远程系统、服务和第三方库,阻止级联故障,在复杂系统中实现恢复能力。

上面有 9 个步骤,每一步骤说明如下:

  1. 每个请求都会封装到 HystrixCommand 中

  2. 请求会以同步或异步的方式进行调用

  3. 判断熔断器是否打开,如果打开,它会直接跳转到 8 ,进行降级

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

  5. 如果前面没有错误,就调用 run 方法,运行依赖逻辑

    运行方法可能会超时,超时后从 5a 到 8,进行降级

  6. 运行过程中如果发生异常,会从 6b 到 8,进行降级

    运行正常会进入 6a,正常返回回去,同时把错误或正常调用结果告诉 7 (Calculate Circuit Health)

  7. Calculate Circuit Health它是 Hystrix 的大脑,是否进行熔断是它通过错误和成功调用次数计算出来的

  8. 降级方法(8a没有实现降级、8b实现降级且成功运行、8c实现降级方法,但是出现异常)

    没有实现降级方法,直接返回异常信息回去

    实现降级方法,且降级方法运行成功,则返回降级后的默认信息回去

    实现降级方法,但是降级也可能出现异常,则返回异常信息回去



五、Hystrix的隔离策略:

    分别是线程隔离THREAD和信号量隔离SEMAPHORE

THREAD(线程隔离):HystrixCommand将会在单独的线程上执行,并发请求受线程池中线程数量的限制。
SEMAPHORE(信号量隔离):HystrixCommand将会在调用线程上执行,开销相对较小,并发请求受信号量的个数的限制。

    两者的对比如下


信号量隔离 线程池隔离
优点 轻量,无额外开销 支持排队和超时
支持异步调用
不足 不支持任务排队和主动超时
不支持异步调用
线程调用会产生额外的开销
适用 受信客户
高扇出(网关)
高频高速调用(cache)
不受信客户
有限扇出


六、Hystrix的熔断参数的判断逻辑

Hystrix 容错处理



 七、Hystrix主要配置参数列表


八、Hystrix关键配置说明

Command Properties

  1. Execution

    1. execution.isolation.strategy

      线程“THREAD”或信号量"SEMAPHORE"隔离(默认:线程“THREAD”

    2. execution.isolation.thread.timeoutInMilliseconds

        run()方法执行超时间(Default:1000)

    3. execution.timeout.enabled

      表示是否开启超时设置。默认值:true

    4. execution.isolation.semaphore.maxConcurrentRequests

      信号量隔离最大并发数(Default:10)

  2. Fallback

    1. fallback.isolation.semaphore.maxConcurrentRequests

      此属性设置从调用线程允许HystrixCommand.getFallback()方法允许的最大并发请求数,默认值:10。对隔离策略THREAD 和SEMAPHORE都起作用。

      如果达到最大的并发量,则接下来的请求会被拒绝并且抛出异常。

    2. fallback.enabled

      是否开启fallback功能,默认值:true。

  3. Circuit Breaker

    1. circuitBreaker.enabled

      是否开启断路器功能,默认值:true。

    2. circuitBreaker.requestVolumeThreshold

      该属性设置滚动窗口中将使断路器跳闸的最小请求数量,默认值:20。

      如果此属性值为20,则在窗口时间内(如10s内),如果只收到19个请求且都失败了,则断路器也不会开启。

    3. circuitBreaker.sleepWindowInMilliseconds

      熔断后重置断路器的时间间隔,默认值:5000。

      断路器跳闸后,在此值的时间的内,hystrix会拒绝新的请求,只有过了这个时间断路器才会打开闸门。

    4. circuitBreaker.errorThresholdPercentage

      熔断的错误百分比阀值,默认值:50。如果失败比率超过这个值,则断路器跳闸并且进入fallback逻辑。

    5. circuitBreaker.forceOpen

      如果设置true,则强制使断路器跳闸,则会拒绝所有的请求。此值会覆盖circuitBreaker.forceClosed的值。默认值:false

    6. circuitBreaker.forceClosed

      如果设置true,则强制使断路器进行关闭状态,此时会允许执行所有请求,无论是否失败的次数达到circuitBreaker.errorThresholdPercentage值。默认值:false

Thread Pool Properties

  1. coreSize 

    使用线程池时的最大并发请求(默认值:10)

  2. maximumSize 

    设置最大的线程池的大小,默认值:10。只有设置allowMaximumSizeToDivergeFromCoreSize时,此值才起作用

  3. maxQueueSize

    设置最大的BlockingQueue队列的值。如果设置-1,则使用SynchronousQueue队列,如果设置正数,则使用LinkedBlockingQueue队列。默认值:-1

  4. queueSizeRejectionThreshold

    队列大小阀值,超过则拒绝。默认值:5。

    因为maxQueueSize值不能被动态修改,所有通过设置此值可以实现动态修改等待队列长度。即等待的队列的数量大于queueSizeRejectionThreshold时(但是没有达到maxQueueSize值),则开始拒绝后续的请求进入队列。如果设置-1,则属性不起作用。


九、hystrix线程池大小及超时设置调优

  1. 一般流程

    (1)一开始先不要设置timeout超时时长,默认就是1000ms,即1s

    (2)一开始也不要设置线程池大小,默认就是10

    (3)直接部署hystrix到生产环境,如果运行的很良好,那么就让它这样运行好了

    (4)让hystrix应用,24小时运行在生产环境中

    (5)依赖标准的监控和报警机制来捕获到系统的异常运行情况

    (6)在24小时之后,看一下调用延迟的占比,以及流量,来计算出让短路器生效的最小的配置数字

    (7)直接对hystrix配置进行热修改,然后继续在hystrix dashboard上监控

    (8)看看修改配置后的系统表现有没有改善

  2. 线程池大小的公式

    每秒的高峰访问次数 * 99%的访问延时 + buffer。

    比如,高峰时,每秒钟访问是30次,99%的情况下,延时在200ms左右,再加个buffer给个4。30 * 0.2 + 4 = 10线程,10个线程每秒处理30次访问应该足够了,每个线程处理3次访问。

  3. 总结

        (1)合理的timeout设置就是99.5%的访问延时。不要设置的太大,否则会导致线程池被占满,然后后续的请求过来大量的reject。

        (2)对于线程池大小来说,一般应该控制在10个左右,20个以内,最少5个


十、相关参考


  • Hystrix 

    https://github.com/Netflix/Hystrix/wiki/Configuration


  • 深入理解微服务中的服务容错思想及模式

    https://blog.csdn.net/weixin_42528780/article/details/114430257


  • 熔断器 Hystrix 的原理与使用

    https://segmentfault.com/a/1190000005988895


  • Spring Cloud Hystrix隔离、熔断、降级实践

    https://blog.csdn.net/zhuyu19911016520/article/details/85346065



以上是关于Hystrix 容错处理的主要内容,如果未能解决你的问题,请参考以下文章

Hystrix 容错处理

Hystrix服务容错处理

SpringCloud+Hystrix服务容错

使用Hystrix实现微服务的容错处理

springcloud-hystrix断路器对微服务的容错处理

将hystrix整合至spring cloud feign实现容错处理