Spring Cloud 教程

Spring Cloud 笔记

Spring Cloud Hystrix 断路器的熔断、限流、信号量等详解

Spring Cloud 断路器详细解析 Spring Cloud 断路器详细解析


Netflix 在 2012 年开源了熔断降级组件 Hystrix。Hystrix 促进了微服务“熔断降级”理念的推广,把隔离和熔断的理念传播到了广大的开发者当中。长期以来,只要一说到隔离和熔断降级,开发者都会首先想到 Hystrix。到了 2014 年,Netflix 全面进军 Spring Cloud,Netflix 的一系列微服务组件也随着 Spring Cloud Netflix 纷至沓来,进入到开发者的视野中;同时,Hystrix 做了一次重大的重构,将底层的统计结构用 rxjava 重构,全面拥抱了 rxjava。长期以来,Hystrix 一直是业界熔断降级库的热门选择,但其社区活跃度一直在下降;最后,Hystrix 宣布停止维护。

支持功能

Hystrix 支持如下功能:

  • 隔离机制:支持两种策略,线程池隔离(默认策略)和信号量隔离
  • 熔断降级机制:基于异常比率的策略。
  • 限流机制:继承隔离机制的手段,使用线程池信号量方式。
  • 动态规则配置:支持多种数据源。
  • 实时统计:基于 RxJava 的滑动窗口

除以上之外,它还具有插件的形式扩展性基于注解的支持简单的监控查看等。

隔离机制

Hystrix 中非常核心的功能之一就是资源隔离,其要解决的主要问题,就是将多个服务的依赖调用分别隔离到各自的资源池内,以避免某个服务的大量调用或超时、失败等导致服务的全部的资源耗费,最终造成整个 service 的崩溃,甚至蔓延到其他服务,进而发生雪崩。

Hystrix 的隔离机制主要使用如下两种技术手段:

  1. 线程池
  2. 信号量

默认情况下,Hystrix 采用线程池的隔离策略

线程池

Hystrix 采用了 Bulkhead Partition 舱壁隔离技术,来将外部依赖进行资源隔离,进而避免任何外部依赖的故障导致本服务崩溃。

舱壁隔离,指的是说将船体内部空间区隔划分成若干个隔舱,一旦某几个隔舱发生破损进水,水流不会在其间相互流动,如此一来船舶在受损时,依然能具有足够的浮力和稳定性,进而减低立即沉船的危险。

舱壁隔离

这里的隔舱在 Hystrix 里就是一个线程池,对每个外部依赖用一个独立的线程池,这样,如果对那个外部依赖调用消耗资源很严重,最多就是耗尽那个依赖自己的线程池而已,不会影响其他的依赖调用,本质上是给提供的服务设置资源上限

线程池的隔离机制也存在着一些缺点,如它额外增加的 CPU 的开销,具体如下:

  • 除了 tomcat 本身的线程池外,Hystrix 自己也管理着线程池,增加了资源的开销。
  • 由于额外线程池的使用,相应的上下文切换的 CPU 开销。

信号量

信号量的资源隔离只是起到一个开关的作用,举例,一个服务 A 的信号量大小为 10(相当于给了 10 个许可证),那就是说它同时只允许有 10 个 tomcat 线程来访问服务 A,其它的请求都会被拒绝,从而达到资源隔离和限流保护的作用。

信号量隔离

Sempahore 技术可以用来限流和削峰,但是不能用来对调用延迟的服务进行 timeout 的隔离。

如果通过信号量调用的时候,若底层的网络调用延迟很严重,那么是无法 timeout 的,只能一直 block 住。一旦请求数量超过了 semephore 限定的数量之后,就会立即开启限流。

线程池与信号量区别

线程池隔离技术,并不是控制类似 tomcat 这种 web 容器级别的线程。严格意义来讲,它控制的是 tomcat 线程的执行。Hystrix 线程池满后,会确保说,tomcat 的线程不会因为依赖服务的接口调用延迟或故障从而被 hang 住,tomcat 其它的线程也不会卡死,可以快速返回,然后去做其它的事情。

线程池隔离技术,是用 Hystrix 自己的线程去执行调用;而信号量隔离技术,是直接让 tomcat 线程去调用依赖服务。信号量隔离,只是一道关卡,信号量有多少,就允许多少个 tomcat 线程通过它,然后去执行。

如下图,清晰地描述了两者的显著区别:

线程池与信号量隔离技术的区别

限流

具体配置参见 Spring Cloud Hystrix 限流配置及实战示例