1.什么是Hystrix

Spring Cloud Hystrix 是一款优秀的服务容错与保护组件,也是 Spring Cloud 中最重要的组件之一。
Spring Cloud Hystrix 是基于 Netflix 公司的开源组件 Hystrix 实现的,它提供了熔断器功能,能够有效地阻止分布式微服务系统中出现联动故障,以提高微服务系统的弹性。Spring Cloud Hystrix 具有服务降级、服务熔断、线程隔离、请求缓存、请求合并以及实时故障监控等强大功能。

2.Hystrix的作用

在微服务系统中,Hystrix 能够帮助我们实现以下目标:

  • 提供降级(FallBack)方案:在请求失败后,提供一个设计好的降级方案,通常是一个兜底方法,当请求失败后即调用该方法。
  • 防止故障扩散:使用熔断机制,防止故障扩散到其他服务。
  • 监控功能:提供熔断器故障监控组件 Hystrix Dashboard,随时监控熔断器的状态。
  • 保护线程资源:防止单个服务的故障耗尽系统中的所有线程资源。
  • 快速失败机制:当某个服务发生了故障,不让服务调用方一直等待,而是直接返回请求失败。

    3.服务降级

    1.什么是服务降级:

  • 在服务器压力剧增时,根据实际业务情况及流量,对一些不重要、不紧急的服务进行有策略地不处理或简单处理从而释放服务器资源以保证核心服务正常运作

  • 当某些服务不可用时,为了避免长时间等待造成服务卡顿或雪崩效应,而主动执行备用的降级逻辑立刻返回一个友好的提示,以保障主体业务不受影响。

    2.服务降级发生的场景

  1. 服务提供者接口抛出异常:触发服务调用者降级逻辑
  2. 服务提供者接口响应超时:触发服务调用者降级逻辑
  3. 服务提供者熔断器处于打开状态:触发服务提供者降级逻辑
  4. 服务调用者线程池资源耗尽:触发服务调用者降级逻辑

    3.服务端降级(不常用)

    服务提供方为了防止对外提供的接口出现异常,进而导致整体服务出现雪崩效应,而提出的一种兜底方案,从而实现异常情况下得友好返回,而不是整个服务调用链的长时间阻塞进而崩溃

    4.客户端降级(常用)

    客户端降级是较常用的一种解决方案。服务调动方为了防止其调用服务出现响应超时等异常情况,当客户端调用的服务端的服务不可用时,客户端直接进行服务降级处理,避免因为IO阻塞造成线程被长时间不必要的占用

    4.整合OpenFeign客户端解耦降级步骤(常用)

    引入依赖

    ```xml org.springframework.cloud spring-cloud-starter-netflix-hystrix
org.springframework.cloud spring-cloud-starter-openfeign

io.github.openfeign feign-httpclient

  1. <a name="tzgqF"></a>
  2. ### 编写feign客户端
  3. ```java
  4. @Component
  5. @FeignClient(value = "service8")
  6. public interface HystrixService {
  7. @GetMapping("api/v1/service8/5")
  8. String get5();
  9. @GetMapping("api/v1/service8/7")
  10. String get7();
  11. }

编写解耦降级逻辑类

  1. @Component
  2. public class HystrixServiceFallback implements HystrixService{
  3. @Override
  4. public String get5() {
  5. return "触发get5熔断";
  6. }
  7. @Override
  8. public String get7() {
  9. return "触发get7熔断";
  10. }
  11. }

通过FeignClient的fallback属性声明降级逻辑类

  1. @Component
  2. @FeignClient(value = "service8", fallback = HystrixServiceFallback.class)
  3. public interface HystrixService {
  4. @GetMapping("api/v1/service8/5")
  5. String get5();
  6. @GetMapping("api/v1/service8/7")
  7. String get7();
  8. }

启动类添加注解

  1. @EnableFeignClients
  2. @EnableEurekaClient
  3. @SpringBootApplication
  4. public class Service3Application {
  5. public static void main(String[] args) {
  6. SpringApplication.run(Service3Application.class, args);
  7. }
  8. }

添加配置

  1. ######################### Ribbon 客户端超时控制 ###################################
  2. ribbon:
  3. ReadTimeout: 7000 #建立连接所用的时间,适用于网络状况正常的情况下,两端两端连接所用的时间
  4. ConnectionTimeout: 7000 #建立连接后,服务器读取到可用资源的时间
  5. ######################### 开启feign调用服务端降级 ###################################
  6. feign:
  7. hystrix:
  8. enabled: true
  9. ###################### 配置默认请求超时时间 ##########################
  10. hystrix:
  11. command:
  12. default:
  13. execution:
  14. isolation:
  15. thread:
  16. timeoutInMilliseconds: 7000
  17. ################### 配置具体方法超时时间########################
  18. HystrixService#get5():
  19. execution:
  20. isolation:
  21. thread:
  22. timeoutInMilliseconds: 5000

PS:

  1. 在配置中需一起声明ribbon与hystrix的超时时间,缺一不可。否则请求时间超过1s就会触发降级逻辑
  2. Hystrix 可以为所有方法设置超时时间(单位为毫秒),若请求超时则触发全局的回退方法进行处理:hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=mmm
  3. Hystrix 还可以为某个特定的服务请求(方法)设置超时时间(单位为毫秒):hystrix.command.xxx#yyy(zzz).execution.isolation.thread.timeoutInMilliseconds=mmm

特定方法超时格式说明如下:

  • xxx:为包含该服务方法的类的名称(通常为Feign服务绑定接口的名称)
  • yyy:服务方法名,例如 get5() 方法。
  • zzz:方法内的参数类型,例如 Integer、String 等等
  • mmm:要设置的超时时间,单位为毫秒

    5.服务端降级步骤(不常用)

    引入依赖

    1. <!--hystrix 依赖-->
    2. <dependency>
    3. <groupId>org.springframework.cloud</groupId>
    4. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    5. </dependency>

    对应方法添加降级策略(通常都是用在Service层面)

    1. @GetMapping
    2. @HystrixCommand(fallbackMethod = "fallBack", commandProperties = {@HystrixProperty(
    3. name = "execution.isolation.thread.timeoutInMilliseconds",
    4. value = "5000")
    5. })
    6. public String get() {
    7. try {
    8. Thread.sleep(3000);
    9. } catch (InterruptedException e) {
    10. e.printStackTrace();
    11. }
    12. return "1111";
    13. }

    启动类添加注解开启服务降级

    1. @EnableCircuitBreaker
    2. @SpringBootApplication
    3. @EnableEurekaClient
    4. public class HystrixApplication {
    5. public static void main(String[] args) {
    6. SpringApplication.run(HystrixApplication.class, args);
    7. }
    8. }

    6.客户端耦合降级步骤(不常用)

    引入依赖

    1. <!--hystrix 依赖-->
    2. <dependency>
    3. <groupId>org.springframework.cloud</groupId>
    4. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    5. </dependency>

    在特定方法以及全局类上声明降级方法

    1. @RestController
    2. @RequestMapping("api/v1/service3")
    3. @DefaultProperties(defaultFallback = "defaultFallback") //声明全局降级方法
    4. public class Controller {
    5. @Resource
    6. private HystrixService hystrixService;
    7. @GetMapping("/5")
    8. @HystrixCommand
    9. public String get5() {
    10. return hystrixService.get5();
    11. }
    12. @GetMapping("/7")
    13. @HystrixCommand(fallbackMethod = "fallback") //单独声明降级方法
    14. public String get7() {
    15. return hystrixService.get7();
    16. }
    17. public String fallback(){
    18. return "触发服务降级,请稍后访问!";
    19. }
    20. public String defaultFallback(){
    21. return "触犯默认降级方法!!!!!!!!!!!!!!!!!!";
    22. }
    23. }

    HystrixService必须是远程feign调用声明的服务接口
    默认降级(defaultFallback)方法必须与其对应的业务方法在同一个类中,否则无法生效。
    全局降级方法的优先级较低,只有业务方法没有指定其降级方法时,服务降级时才会触发全局回退方法。若业务方法指定它自己的回退方法,那么在服务降级时,就只会直接触发它自己的回退方法,而非全局回退方法。

    添加配置

    ```yaml

    ################### 开启feign调用服务端降级

    feign: hystrix: enabled: true

################ 配置默认请求超时时间

hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 7000

  1. ################### 配置具体方法超时时间########################
  2. HystrixService#get5():
  3. execution:
  4. isolation:
  5. thread:
  6. timeoutInMilliseconds: 5000
  1. <a name="SLkeU"></a>
  2. ### 启动类添加注解
  3. ```java
  4. @EnableHystrix
  5. @EnableFeignClients
  6. @EnableEurekaClient
  7. @SpringBootApplication
  8. public class Service3Application {
  9. public static void main(String[] args) {
  10. SpringApplication.run(Service3Application.class, args);
  11. }
  12. }

7.服务熔断

熔断机制是为了应对雪崩效应而出现的一种微服务链路保护机制。
当微服务系统中的某个微服务不可用或响应时间太长时,为了保护系统的整体可用性,熔断器会暂时切断请求对该服务的调用,并快速返回一个友好的错误响应。这种熔断状态不是永久的,在经历了一定的时间后,熔断器会再次检测该微服务是否恢复正常,若服务恢复正常则恢复其调用链路。
熔断共包含三种状态:

  1. 熔断关闭状态(Closed):当务访问正常时,熔断器处于关闭状态,服务调用方可以正常地对服务进行调用。
  2. 熔断开启状态(Open):默认情况下,在固定时间内接口调用出错比率达到一个阈值(例如 50%),熔断器会进入熔断开启状态。进入熔断状态后,后续对该服务的调用都会被切断,熔断器会执行本地的降级(FallBack)方法。
  3. 半熔断状态(Half-Open): 在熔断开启一段时间之后,熔断器会进入半熔断状态。在半熔断状态下,熔断器会尝试恢复服务调用方对服务的调用,允许部分请求调用该服务,并监控其调用成功率。如果成功率达到预期,则说明服务已恢复正常,熔断器进入关闭状态;如果成功率仍旧很低,则重新进入熔断开启状态。

转化如图:
image.png

8.Hystrix熔断

在 Spring Cloud 中,熔断机制是通过 Hystrix 实现的。Hystrix 会监控微服务间调用的状况,当失败调用到一定比例时(例如 5 秒内失败 20 次),就会启动熔断机制。
Hystrix 实现服务熔断的步骤如下:

  1. 当服务的调用出错率达到或超过 Hystix 规定的比率(默认为 50%)后,熔断器进入熔断开启状态。
  2. 熔断器进入熔断开启状态后,Hystrix 会启动一个休眠时间窗,在这个时间窗内,该服务的降级逻辑会临时充当业务主逻辑,而原来的业务主逻辑不可用。
  3. 当有请求再次调用该服务时,会直接调用降级逻辑快速地返回失败响应,以避免系统雪崩。
  4. 当休眠时间窗到期后,Hystrix 会进入半熔断转态,允许部分请求对服务原来的主业务逻辑进行调用,并监控其调用成功率。
  5. 如果调用成功率达到预期,则说明服务已恢复正常,Hystrix 进入熔断关闭状态,服务原来的主业务逻辑恢复;否则 Hystrix 重新进入熔断开启状态,休眠时间窗口重新计时,继续重复第 2 到第 5 步

    9.Hystrix熔断机制的实现

    熔断个人认为一般是从服务提供者的角度去考虑

    引入依赖

    1. <!--hystrix 依赖-->
    2. <dependency>
    3. <groupId>org.springframework.cloud</groupId>
    4. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    5. </dependency>

    在具体方法添加@HystrixCommand标签

    ```java @GetMapping(“/{id}”) @HystrixCommand(fallbackMethod = “fallback”, commandProperties = { //以下参数在 HystrixCommandProperties 类中有默认配置 @HystrixProperty(name = “circuitBreaker.enabled”, value = “true”), //是否开启熔断器 @HystrixProperty(name = “circuitBreaker.sleepWindowInMilliseconds”, value = “10000”), //休眠时间窗口期 @HystrixProperty(name = “metrics.rollingStats.timeInMilliseconds”,value = “5000”), //统计时间窗 @HystrixProperty(name = “circuitBreaker.requestVolumeThreshold”, value = “10”), //统计时间窗内请求次数 @HystrixProperty(name = “circuitBreaker.errorThresholdPercentage”, value = “60”), //在统计时间窗口期以内,请求失败率达到 60% 时进入熔断状态 }) public String getInt(@PathVariable Integer id) { if (id < 0) {
    1. throw new RuntimeException("不能小于0");
    } else {
    1. return "干得漂亮:" + id;
    } }

public String fallback(Integer id){ return “进入熔断逻辑了SB!”; }

  1. **PSfallback方法参数必须和具体业务方法参数、返回值一致,不然会报错**
  2. <a name="v0GVC"></a>
  3. ### 启动类添加注解
  4. ```java
  5. import org.springframework.boot.SpringApplication;
  6. import org.springframework.boot.autoconfigure.SpringBootApplication;
  7. import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
  8. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  9. @EnableCircuitBreaker
  10. @SpringBootApplication
  11. @EnableEurekaClient
  12. public class Service4Application {
  13. public static void main(String[] args) {
  14. SpringApplication.run(Service4Application.class, args);
  15. }
  16. }

@HystrixCommand标签参数说明:

参数 描述
metrics.rollingStats.timeInMilliseconds 统计时间窗。
circuitBreaker.requestVolumeThreshold 请求总数阀值。
在统计时间窗内,请求总数必须到达一定的数量级,Hystrix 才可能会将熔断器打开进入熔断开启转态,而这个请求数量级就是 请求总数阀值。Hystrix 请求总数阈值默认为 20,这就意味着在统计时间窗内,如果服务调用次数不足 20 次,即使所有的请求都调用出错,熔断器也不会打开。
circuitBreaker.errorThresholdPercentage 错误百分比阈值。
当请求总数在统计时间窗内超过了请求总数阀值,且请求调用出错率超过一定的比例,熔断器才会打开进入熔断开启转态,而这个比例就是错误百分比阈值。错误百分比阈值设置为 50,就表示错误百分比为 50%,如果服务发生了 30 次调用,其中有 15 次发生了错误,即超过了 50% 的错误百分比,这时候将熔断器就会打开。
circuitBreaker.sleepWindowInMilliseconds 休眠时间窗,熔断开启状态持续一段时间后,熔断器会自动进入半熔断状态,这段时间就被称为休眠窗口期。

9.Hystrix监控

参考这里:点击这里

10.总结

Hystrix为微服务间系统调用提供了服务降级、服务熔断等容错机制,提高了微服务系统的健壮性
作为服务提供者,通过熔断机制避免了当请求不可用时,造成长时间请求阻塞引发雪崩效应。并且通过熔断窗口期给了服务恢复正常的缓冲时间
作为服务调用者,通过指定fallback实现类,保证了其调用的服务在不可用时,以解耦降级的方式通过降级机制进行一个兜底的友好返回。进而避免调用的服务不可用引发的雪崩效应。
总体上来讲,都是为了提高系统的健壮性以及容错性,保证了整个微服务系统的高可用性