Skip to content

一、概述

Hystrix是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。Hystrix主要通过以下几点实现延迟和容错。

包裹请求:使用HystrixCommand包裹对依赖的调用逻辑,每个命令在独立线程中执行。这使用了设计模式中的“命令模式”。

跳闸机制:当某服务的错误率超过一定的阈值时,Hystrix可以自动或手动跳闸,停止请求该服务一段时间。

资源隔离:Hystrix为每个依赖都维护了一个小型的线程池(或者信号量)。如果该线程池已满,发往该依赖的请求就被立即拒绝,而不是排队等待,从而加速失败判定。

监控:Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时、以及被拒绝的请求等。

回退机制:当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑。回退逻辑由开发人员

自行提供,例如返回一个缺省值。

自我修复:断路器打开一段时间后,会自动进入“半开”状态。

熔断机制是应对雪崩效应的一种微服务链路保护机制。

当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速响应错误信息。当检测到该节点微服务调用响应正常后恢复调用链路。

1.1 熔断器的状态

熔断器有三个状态 CLOSED 、 OPEN 、 HALF_OPEN 熔断器默认关闭状态,当触发熔断后状态变更为OPEN ,在等待到指定的时间,Hystrix会放请求检测服务是否开启,这期间熔断器会变为 HALF_OPEN 半开启状态,熔断探测服务可用则继续变更为 CLOSED 关闭熔断器。

Closed:关闭状态(断路器关闭),所有请求都正常访问。代理类维护了最近调用失败的次数,如果某次调用失败,则使失败次数加1。如果最近失败次数超过了在给定时间内允许失败的阈值,则代理类切换到断开(Open)状态。此时代理开启了一个超时时钟,当该时钟超过了该时间,则切换到半断开(Half-Open)状态。该超时时间的设定是给了系统一次机会来修正导致调用失败的错误。

Open:打开状态(断路器打开),所有请求都会被降级。Hystix会对请求情况计数,当一定时间内失败请求百分比达到阈值,则触发熔断,断路器会完全关闭。默认失败比例的阈值是50%,请求次数最少不低于20次。

Half Open:半开状态,open状态不是永久的,打开后会进入休眠时间(默认是5S)。随后断路器会自动进入半开状态。此时会释放1次请求通过,若这个请求是健康的,则会关闭断路器,否则继续保持打开,再次进行5秒休眠计时

1.2 熔断器的隔离策略

微服务使用Hystrix熔断器实现了服务的自动降级,让微服务具备自我保护的能力,提升了系统的稳定性,也较好的解决雪崩效应。其使用方式目前支持两种策略:

  • 线程池隔离策略:使用一个线程池来存储当前的请求,线程池对请求作处理,设置任务返回处理超时时间,堆积的请求堆积入线程池队列。这种方式需要为每个依赖的服务申请线程池,有一定的资源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队里慢慢处理)

  • 信号量隔离策略:使用一个原子计数器(或信号量)来记录当前有多少个线程在运行,请求来先判断计数器的数值,若超过设置的最大线程个数则丢弃改类型的新请求,若不超过则执行计数操作请求来计数器+1,请求返回计数器-1。这种方式是严格的控制线程且立即返回模式,无法应对突发流量(流量洪峰来临时,处理的线程超过数量,其他的请求会直接返回,不继续去请求依赖的服务)

线程池和型号量两种策略功能支持对比如下:

功能线程池隔离信号量隔离
线程与调用线程非相同线程与调用线程相同(jetty线程)
开销排队、调度、上下文开销等无线程切换,开销低
异步支持不支持
并发量支持支持(最大线程池大小)支持(最大线程池大小)

hystrix.command.default.execution.isolation.strategy : 配置隔离策略

  • ExecutionIsolationStrategy.SEMAPHORE 信号量隔离
  • ExecutionIsolationStrategy.THREAD 线程池隔离

hystrix.command.default.execution.isolation.maxConcurrentRequests : 最大信号量上限

二、使用Demo

2.1 使用示例

依赖

xml
<dependency> 
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

配置

yml
#消费端    
feign: 
  hystrix: 
    enabled: true

hystrix:
 command:
    default:
   execution:
        isolation:
       thread:
            timeoutInMilliseconds: 6000 # 设置hystrix的超时时间为6000ms
            
#触发熔断的最小请求次数,默认20
#circuitBreaker.requestVolumeThreshold=10
#休眠时长,默认是5000毫秒
#circuitBreaker.sleepWindowInMilliseconds=10000
#触发熔断的失败请求最小占比,默认50%
# circuitBreaker.errorThresholdPercentage=50


<NolebasePageProperties />

使用

java
// 提供端熔断
// 用于controller层,指定出现异常时快速返回的方法。
@HystrixCommand(fallbackMethod="hystrixGet")

// 消费端降级
// 通过继承FallbackFactory或实现调用接口重写方法
// 启动类需要添加 `@EnableCircuitBreaker`注解
@FeignClient(fallback='实现api接口得熔断类',factory='构建快速返回得工厂类')

2.2 熔断监控

监控端依赖

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- hystrix和 hystrix-dashboard相关 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>

<!-- 启动类添加@EnableHystrixDashboard -->

被控端依赖

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

监控信息查看

首页: hystrix监控的url+端口/hystix
数据: 被监控的模块url+端口/hystrix.stream
图形化显示,在首页输入框中输入数据的url

2.3 断路器聚合监控Turbine

依赖

xml
<dependency> 
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>
<dependency> 
    <groupId>org.springframework.cloud</groupId> 
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> 
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

配置

yml
server:
  port: 8031 
spring: 
  application: 
    name: microservice-hystrix-turbine 
  eureka: 
    client: 
      service-url:
        defaultZone: http://localhost:8761/eureka/ 
    instance:
      prefer-ip-address: true 
turbine: # 要监控的微服务列表,多个用,分隔 
  appConfig: shop-service-order 
  clusterNameExpression: "'default'"

turbine会自动的从注册中心中获取需要监控的微服务,并聚合所有微服务中的 /hystrix.stream 数据

使用

配置启动类

java
@EnableTurbine
@EnableHystrixDashboard

浏览器访问 http://localhost:8031/hystrix 展示HystrixDashboard。并在url位置输入 http://localhost:8031/turbine.stream,动态根据turbine.stream数据展示多个微服务的监控数据