微服务入门(六) | 五大核心组件之Hystrix

目录

定义

目的

实现原理

工作流程

容错机制

资源隔离

线程池隔离技术

信号量隔离技术

服务熔断

服务熔断简介(见服务雪崩与熔断)

工作流程

服务降级

服务降级简介

触发条件

使用方法

降级方式

Reference


  • 定义

Hystrix是一个应用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等。Hystrix能够保证在一个依赖出问题的情况下,不会导致整个体系服务失败,避免级联故障,以提高分布式系统的弹性。

  • 目的

    • 对来自依赖的延迟和故障进行防护和控制(通常是通过网络访问的依赖)
    • 阻止故障的连锁反应(服务雪崩,见服务雪崩与熔断
    • 快速失败并迅速恢复
    • 回退并优雅降级
    • 提供近实时的监控与告警
  • 实现原理

    • 使用命令模式将所有对外部服务(或依赖关系)的调用包装在HystrixCommand或HystrixObservableCommand对象中,并将该对象放在单独的线程中执行;
    • 每个依赖都维护着一个线程池(或信号量),线程池被耗尽则拒绝请求(而不是让请求排队)。
    • 记录请求成功,失败,超时和线程拒绝。
    • 服务错误百分比超过了阈值,熔断器开关自动打开,一段时间内停止对该服务的所有请求。
    • 请求失败,被拒绝,超时或熔断时执行降级逻辑。
    • 近实时地监控指标和配置的修改。
  • 工作流程

    • 构造一个 HystrixCommand或HystrixObservableCommand对象,用于封装请求,并在构造方法配置请求被执行需要的参数
    • 执行命令
      • execute()
        • 同步堵塞方式执行run(),只支持接收一个值对象
        • hystrix会从线程池中取一个线程来执行run(),并等待返回值。
      • queue()
        • 异步非阻塞方式执行run(),只支持接收一个值对象。
        • 调用queue()就直接返回一个Future对象。可通过 Future.get()拿到run()的返回结果,但Future.get()是阻塞执行的。若执行成功,Future.get()返回单个返回值。当执行失败时,如果没有重写fallback,Future.get()抛出异常。
      • observe()
        • 事件注册前执行run()/construct(),支持接收多个值对象,取决于发射源。
        • 会返回一个hot Observable,也就是说,调用observe()自动触发执行run()/construct(),无论是否存在订阅者。
        • 如果继承的是HystrixCommand,hystrix会从线程池中取一个线程以非阻塞方式执行run();如果继承的是HystrixObservableCommand,将以调用线程阻塞执行construct()。
        • 使用方法:
          • 调用observe()会返回一个Observable对象
          • 调用这个Observable对象的subscribe()方法完成事件注册,从而获取结果
      • toObservable()
        • 事件注册后执行run()/construct(),支持接收多个值对象,取决于发射源。
        • 会返回一个cold Observable,也就是说,调用toObservable()不会立即触发执行run()/construct(),必须有订阅者订阅Observable时才会执行。
        • 如果继承的是HystrixCommand,hystrix会从线程池中取一个线程以非阻塞方式执行run(),调用线程不必等待run();如果继承的是HystrixObservableCommand,将以调用线程堵塞执行construct(),调用线程需等待construct()执行完才能继续往下走。
      • 需注意的是,HystrixCommand也支持toObservable()和observe(),但是即使将HystrixCommand转换成Observable,它也只能发射一个值对象。只有HystrixObservableCommand才支持发射多个值对象。
    • 判断是否使用缓存响应请求,若启用了缓存,且缓存可用,直接使用缓存响应请求。Hystrix支持请求缓存,但需要用户自定义启动
    • 判断熔断器是否打开,如果打开,跳到Fallback
    • 判断线程池/队列/信号量是否已满,已满则跳到Fallback
    • 执行HystrixObservableCommand.construct()或HystrixCommand.run(),如果执行失败或者超时,跳到Fallback;否则,直接返回请求响应
    • 统计熔断器监控指标
    • 走Fallback备用逻辑
    • 返回请求响应
  • 容错机制

    • 资源隔离

资源隔离,就是将多个依赖服务的调用分别隔离到各个资源的内部,避免因为依赖服务的失败或者延迟,导致服务所有的线程资源花费在这个伤害,继而导致服务崩塌。

      • hystrix中主要有两种资源隔离的技术:线程池隔离和信号量隔离。
      • 线程池隔离技术

线程池隔离技术,是用自己的线程去调用web容器,控制web容器中线程的执行,而非web容器本身的线程。出现问题会抛出异常,在web容器的执行线程中可以捕获到,然后做进一步的处理。 

        • 使用场景

大部分的场景下其实都适合用这种技术,对于依赖服务的调用以及访问;能解决timeout的场景,可以避免调用线程阻塞住。

      • 信号量隔离技术

信号量隔离技术是直接让web容器的线程直接去调用依赖服务,出现问题直接返回。

        • 使用场景
          • 通常是针对超大并发量的场景,每个服务实例的QPS都非常高,如果用线程池,可能撑不住那么高的并发,如果要撑住,可能要耗费大量的线程资源,那么就是用信号量,来进行限流保护。
          • 适合访问不依赖于外部服务,而只是访问内部的一些复杂的业务逻辑,由于是内部访问,不存在timeout的问题,适合比较复杂逻辑的业务代码,防止大量的线程被这些逻辑给卡死,影响系统的稳定性。
    • 服务熔断

      • 服务熔断简介(见服务雪崩与熔断

      • 工作流程

        • 调用allowRequest()判断是否允许将请求提交到线程池
          • 如果熔断器强制打开,circuitBreaker.forceOpen为true,不允许放行,返回。
          • 如果熔断器强制关闭,circuitBreaker.forceClosed为true,允许放行。此外不必关注熔断器实际状态,也就是说熔断器仍然会维护统计数据和开关状态,只是不生效而已。
        • 调用isOpen()判断熔断器开关是否打开
          • 如果熔断器开关打开,进入第三步,否则继续;
          • 如果一个周期内总的请求数小于circuitBreaker.requestVolumeThreshold的值,允许请求放行,否则继续;
          • 如果一个周期内错误率小于circuitBreaker.errorThresholdPercentage的值,允许请求放行。否则,打开熔断器开关,进入第三步。
        • 用allowSingleTest()判断是否允许单个请求通行,检查依赖服务是否恢复
          • 如果熔断器打开,且距离熔断器打开的时间或上一次试探请求放行的时间超过circuitBreaker.sleepWindowInMilliseconds的值时,熔断器器进入半开状态,允许放行一个试探请求;否则,不允许放行。
    • 服务降级

      • 服务降级简介

      • 触发条件

        • 执行construct()或run()抛出异常
        • 熔断器打开导致命令短路
        • 命令的线程池和队列或信号量的容量超额,命令被拒绝
        • 命令执行超时
      • 使用方法

        • 重写HystrixObservableCommand的resumeWithFallback方法或HystrixCommand的getFallBack方法
      • 降级方式

        • Fail Fast 快速失败

快速失败是最普通的命令执行方法,命令没有重写降级逻辑。 如果命令执行发生任何类型的故障,它将直接抛出异常。

            • Fail Silent 无声失败

指在降级方法中通过返回null,空Map,空List或其他类似的响应来完成。

            • Fallback: Static

指在降级方法中返回静态默认值。 这不会导致服务以“无声失败”的方式被删除,而是导致默认行为发生。如:应用根据命令执行返回true / false执行相应逻辑,但命令执行失败,则默认为true。

            • Fallback: Stubbed

当命令返回一个包含多个字段的复合对象时,适合以Stubbed 的方式回退。

            • Fallback: Cache via Network

有时,如果调用依赖服务失败,可以从缓存服务(如redis)中查询旧数据版本。由于又会发起远程调用,所以建议重新封装一个Command,使用不同的ThreadPoolKey,与主线程池进行隔离。

            • Primary + Secondary with Fallback
              • 有时系统具有两种行为:主要和次要 或 主要和故障转移。
              • 主要和次要逻辑涉及到不同的网络调用和业务逻辑,所以需要将主次逻辑封装在不同的Command中,使用线程池进行隔离。为了实现主从逻辑切换,可以将主次command封装在外观HystrixCommand的run方法中,并结合配置中心设置的开关切换主从逻辑。
              • 由于主次逻辑都是经过线程池隔离的HystrixCommand,因此外观HystrixCommand可以使用信号量隔离,而没有必要使用线程池隔离引入不必要的开销。
  • Reference

  • spring官方文档

https://spring.io/projects/spring-cloud-netflix

  • 【狂神说Java】SpringCloud最新教程IDEA版

https://www.bilibili.com/video/BV1jJ411S7xr

  • Hystrix原理与实战

https://blog.csdn.net/loushuiyifan/article/details/82702522

  • Hystrix的原理及使用

https://blog.csdn.net/qq_38149225/article/details/109454418

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值