SpringCloud Hystrix

x33g5p2x  于2021-12-21 转载在 其他  
字(23.9k)|赞(0)|评价(0)|浏览(385)

1.Hystrix 简介

Hystrix熔断器:正常是一个关闭状态,触发也就是当你错误次数超过一个值时候(值可以设置),就会打开(不再提供服务)状态,相当于跳闸,但是有一个恢复时间,之后半开的状态配置一个失败率也就是之后小于这个失败率就可以进行一个全开如果超过的话就会重新打开.

1.1 什么是灾难性雪崩效应

造成灾难性雪崩效应的原因,可以简单归结为下述三种:
服务提供者不可用。如:硬件故障、程序 BUG、缓存击穿、并发请求量过大等。
重试加大流量。如:用户重试、代码重试逻辑等。
服务调用者不可用。如:同步请求阻塞造成的资源耗尽等。

  • 雪崩效应最终的结果就是:服务链条中的某一个服务不可用,导致一系列的服务不可用,最终造成服务逻辑崩溃。这种问题造成的后果,往往是无法预料的。
  • 解决灾难性雪崩效应的方式通常有:降级、熔断和请求缓存。

1.2 什么是 Hystrix

  • Hystrix [hɪst’rɪks],中文含义是豪猪,因其背上长满棘刺,从而拥有了自我保护的能力。本文所说的 Hystrix 是 Netflix 开源的一款容错框架,同样具有自我保护能力。为了实现容错和自我保护,下面我们看看 Hystrix 如何设计和实现的。

Hystrix 设计目标:

  • 对来自依赖的延迟和故障进行防护和控制——这些依赖通常都是通过网络访问的
  • 阻止故障的连锁反应
  • 快速失败并迅速恢复
  • 回退并优雅降级
  • 提供近实时的监控与告警

Hystrix 遵循的设计原则:

  • 防止任何单独的依赖耗尽资源(线程)
  • 过载立即切断并快速失败,防止排队
  • 尽可能提供回退以保护用户免受故障
  • 使用隔离技术(例如隔板,泳道和断路器模式)来限制任何一个依赖的影响
  • 通过近实时的指标,监控和告警,确保故障被及时发现
  • 通过动态修改配置属性,确保故障及时恢复
  • 防止整个依赖客户端执行失败,而不仅仅是网络通信

Hystrix 如何实现这些设计目标?

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

在 Spring cloud 中处理服务雪崩效应,都需要依赖 hystrix 组件。在 Application Client 应用的 pom 文件中都需要引入下述依赖:

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

2.服务降级

  • 降级是指,当请求超时、资源不足等情况发生时进行服务降级处理,不调用真实服务逻辑,而是使用快速失败(fallback)方式直接返回一个托底数据,保证服务链条的完整,避免服务雪崩。
  • 解决服务雪崩效应,都是避免 application client 请求 application service 时,出现服务调用错误或网络问题。处理手法都是在 application client 中实现。
  • 我们需要在 application client 相关工程中导入 hystrix 依赖信息。并在对应的启动类上增加新的注解 @EnableCircuitBreaker,这个注解是用于开启 hystrix 熔断器的,简言之,就是让代码中的 hystrix 相关注解生效。
  • 具体实现过程如下:

2.1 修改 application service 代码

  • 修改 application service 工程中的代码,模拟超时错误。此模拟中,让服务端代码返回之前休眠 2000 毫秒,替代具体的复杂服务逻辑。
  1. package com.csdn.controller;
  2. import org.springframework.web.bind.annotation.GetMapping;
  3. import org.springframework.web.bind.annotation.RestController;
  4. @RestController
  5. public class ServiceController {
  6. @GetMapping
  7. public Object first(){
  8. try {
  9. // 用于模拟远程服务调用延时。
  10. Thread.sleep(2000);
  11. }catch (InterruptedException e) {
  12. e.printStackTrace();
  13. }
  14. return "测试 Spring Cloud Netflix Ribbon 开发服务提供者";
  15. }
  16. }

2.2 application client POM 依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  5. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  6. <parent>
  7. <artifactId>cloudhystrix</artifactId>
  8. <groupId>com.csdn</groupId>
  9. <version>1.0-SNAPSHOT</version>
  10. </parent>
  11. <modelVersion>4.0.0</modelVersion>
  12. <artifactId>applicationclient</artifactId>
  13. <dependencies>
  14. <dependency>
  15. <groupId>org.springframework.boot</groupId>
  16. <artifactId>spring-boot-starter-web</artifactId>
  17. </dependency>
  18. <dependency>
  19. <groupId>org.springframework.cloud</groupId>
  20. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.cloud</groupId>
  24. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  25. </dependency>
  26. </dependencies>
  27. </project>

2.3 application client 容错处理代码

  1. package com.csdn.service.impl;
  2. import com.csdn.service.ClientService;
  3. import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.cloud.client.ServiceInstance;
  6. import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
  7. import org.springframework.core.ParameterizedTypeReference;
  8. import org.springframework.http.HttpMethod;
  9. import org.springframework.http.ResponseEntity;
  10. import org.springframework.stereotype.Service;
  11. import org.springframework.web.client.RestTemplate;
  12. @Service
  13. public class ClientServiceImpl implements ClientService {
  14. @Autowired
  15. private LoadBalancerClient loadBalancerClient;
  16. // HystrixCommand - 开启 Hystrix 容错处理的注解。代表当前方法如果出现服务调用问题,使用 Hystrix 容错处理逻辑来处理
  17. //属性 fallbackMethod - 如果当前方法调用服务,远程服务出现问题的时候,调用本地的哪个方法得到托底数据。
  18. @HystrixCommand(fallbackMethod = "downgradeFallback")
  19. @Override
  20. public String first() {
  21. ServiceInstance si = this.loadBalancerClient.choose("application-service");
  22. StringBuilder sb = new StringBuilder();
  23. sb.append("http://").append(si.getHost()).append(":").append(si.getPort()).append("/");
  24. System.out.println("本次访问的 service 是: " + sb.toString());
  25. RestTemplate rt = new RestTemplate();
  26. ParameterizedTypeReference<String> type = new ParameterizedTypeReference<String>() { };
  27. ResponseEntity<String> response = rt.exchange(sb.toString(), HttpMethod.GET, null, type);
  28. String result = response.getBody();
  29. return result;
  30. }
  31. // 本地容错方法,只有远程服务调用过程出现问题的时候,才会调用此方法,获取托底数据。保证服务完整性。
  32. private String downgradeFallback(){
  33. return "服务降级方法返回托底数据";
  34. }
  35. }

2.4 application client 配置文件 application.yml

  1. server:
  2. port: 8082
  3. spring:
  4. application:
  5. name: application-client
  6. eureka:
  7. client:
  8. service-url:
  9. defaultZone:
  10. - http://localhost:8761/eureka/
  11. hystrix:
  12. command:
  13. default:
  14. execution:
  15. timeout:
  16. # 如果 enabled 设置为 false,则请求超时交给 ribbon 控制,为 true,则超时作为容错根据
  17. enabled: true
  18. isolation:
  19. thread:
  20. timeoutInMilliseconds: 1000 # 超时时间,默认 1000ms

2.5 application client 启动类

  1. package com.csdn;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
  5. // @EnableCircuitBreaker - 开启 Hystrix 容错处理能力。
  6. // 如果不使用此注解,服务代码中的@HystrixCommand 注解无效。
  7. @SpringBootApplication
  8. @EnableCircuitBreaker
  9. public class ClientApp {
  10. public static void main(String[] args) {
  11. SpringApplication.run(ClientApp.class, args);
  12. }
  13. }

3.服务熔断

  • 当一定时间内,异常请求比例(请求超时、网络故障、服务异常等)达到阀值时,启动熔断器,熔断器一旦启动,则会停止调用具体服务逻辑,通过 fallback 快速返回托底数据,保证服务链的完整
  • 熔断有自动恢复机制,如:当熔断器启动后,每隔 5 秒,尝试将新的请求发送给服务提供者,如果服务可正常执行并返回结果,则关闭熔断器,服务恢复。如果仍旧调用失败,则继续返回托底数据,熔断器持续开启状态。

3.1 application client POM 依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  5. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  6. <parent>
  7. <artifactId>cloudhystrix</artifactId>
  8. <groupId>com.csdn</groupId>
  9. <version>1.0-SNAPSHOT</version>
  10. </parent>
  11. <modelVersion>4.0.0</modelVersion>
  12. <artifactId>applicationclient</artifactId>
  13. <dependencies>
  14. <dependency>
  15. <groupId>org.springframework.boot</groupId>
  16. <artifactId>spring-boot-starter-web</artifactId>
  17. </dependency>
  18. <dependency>
  19. <groupId>org.springframework.cloud</groupId>
  20. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.cloud</groupId>
  24. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  25. </dependency>
  26. </dependencies>
  27. </project>

3.2 application client 容错处理代码

  1. package com.csdn.service.impl;
  2. import com.csdn.service.ClientService;
  3. import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
  4. import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
  5. import com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.cloud.client.ServiceInstance;
  8. import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
  9. import org.springframework.core.ParameterizedTypeReference;
  10. import org.springframework.http.HttpMethod;
  11. import org.springframework.http.ResponseEntity;
  12. import org.springframework.stereotype.Service;
  13. import org.springframework.web.client.RestTemplate;
  14. @Service
  15. public class ClientServiceImpl implements ClientService {
  16. @Autowired
  17. private LoadBalancerClient loadBalancerClient;
  18. //@HystrixCommand - 开启 Hystrix 容错处理的注解。代表当前方法如果出现服务调用问题,使用 Hystrix 容错处理逻辑来处理
  19. //属性 fallbackMethod - 如果当前方法调用服务,远程服务出现问题的时候,调用本地的哪个方法得到托底数据
  20. @HystrixCommand(fallbackMethod = "downgradeFallback", commandProperties = {
  21. // 默认 20 个;10s 内请求数大于 20 个时就启动熔断器,当请求符合熔断条件时将触发 fallback 逻辑
  22. @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, value = "10"),
  23. // 请求错误率大于 50%时就熔断,然后 for 循环发起请求,当请求符合熔断 条件时将触发
  24. @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, value = "50"),
  25. // 默认 5 秒;熔断多少秒后去尝试请求
  26. @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value = "5000")
  27. }
  28. )
  29. @Override
  30. public String first() {
  31. ServiceInstance si = this.loadBalancerClient.choose("application-service");
  32. StringBuilder sb = new StringBuilder();
  33. sb.append("http://").append(si.getHost()).append(":").append(si.getPort()).append("/");
  34. System.out.println("本次访问的 service 是: " + sb.toString());
  35. RestTemplate rt = new RestTemplate();
  36. ParameterizedTypeReference<String> type = new ParameterizedTypeReference<String>() { };
  37. ResponseEntity<String> response = rt.exchange(sb.toString(), HttpMethod.GET, null, type);
  38. String result = response.getBody();
  39. return result;
  40. }
  41. // 本地容错方法,只有远程服务调用过程出现问题的时候,才会调用此方法,获取托底数据。保证服务完整性。
  42. private String downgradeFallback(){
  43. return "服务降级方法返回托底数据";
  44. }
  45. }

3.3 application client 配置文件 application.yml

  1. server:
  2. port: 8082
  3. spring:
  4. application:
  5. name: application-client
  6. eureka:
  7. client:
  8. service-url:
  9. defaultZone:
  10. - http://localhost:8761/eureka/
  11. hystrix:
  12. command:
  13. default:
  14. execution:
  15. timeout:
  16. # 如果 enabled 设置为 false,则请求超时交给 ribbon 控制,为 true,则超时作为容错根据
  17. enabled: true
  18. isolation:
  19. thread:
  20. timeoutInMilliseconds: 1000 # 超时时间,默认 1000ms

3.4 application client 启动类

  1. package com.csdn;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
  5. //@EnableCircuitBreaker - 开启 Hystrix 容错处理能力。
  6. //如果不使用此注解,服务代码中的@HystrixCommand 注解无效。
  7. @SpringBootApplication
  8. @EnableCircuitBreaker
  9. public class ClientApp {
  10. public static void main(String[] args) {
  11. SpringApplication.run(ClientApp.class, args);
  12. }
  13. }

4.请求缓存

  • 请求缓存:通常意义上说,就是将同样的 GET 请求结果缓存起来,使用缓存机制(如 redis、mongodb)提升请求响应效率。
  • 使用请求缓存时,需要注意非幂等性操作对缓存数据的影响。
  • 请求缓存是依托某一缓存服务来实现的。在案例中使用 redis 作为缓存服务器,那么可以使用 spring-data-redis 来实现 redis 的访问操作。

4.1 修改 application service 代码

  1. package com.csdn.controller;
  2. import org.springframework.web.bind.annotation.GetMapping;
  3. import org.springframework.web.bind.annotation.PostMapping;
  4. import org.springframework.web.bind.annotation.RestController;
  5. @RestController
  6. public class ServiceController {
  7. @PostMapping("/testPost")
  8. public Object testPost(){
  9. System.out.println("testPost method run");
  10. return "写操作返回";
  11. }
  12. @GetMapping("/testGet")
  13. public Object testGet(){
  14. System.out.println("testGet method run");
  15. return "读操作返回";
  16. }
  17. @GetMapping
  18. public Object first(){
  19. System.out.println("run");
  20. try {
  21. // 用于模拟远程服务调用延时。
  22. Thread.sleep(2000);
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. }
  26. return "测试 Spring Cloud Netflix Ribbon 开发服务提供者";
  27. }
  28. }

4.2 application client POM 依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  5. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  6. <parent>
  7. <artifactId>cloudhystrix</artifactId>
  8. <groupId>com.csdn</groupId>
  9. <version>1.0-SNAPSHOT</version>
  10. </parent>
  11. <modelVersion>4.0.0</modelVersion>
  12. <artifactId>applicationclient</artifactId>
  13. <dependencies>
  14. <dependency>
  15. <groupId>org.springframework.boot</groupId>
  16. <artifactId>spring-boot-starter-web</artifactId>
  17. </dependency>
  18. <dependency>
  19. <groupId>org.springframework.cloud</groupId>
  20. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter-data-redis</artifactId>
  25. </dependency>
  26. <dependency>
  27. <groupId>org.springframework.cloud</groupId>
  28. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  29. </dependency>
  30. </dependencies>
  31. </project>

4.3 application client 容错处理代码

  1. package com.csdn.service.impl;
  2. import com.csdn.service.ClientService;
  3. import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
  4. import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
  5. import com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.cache.annotation.CacheConfig;
  8. import org.springframework.cache.annotation.CacheEvict;
  9. import org.springframework.cache.annotation.Cacheable;
  10. import org.springframework.cloud.client.ServiceInstance;
  11. import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
  12. import org.springframework.core.ParameterizedTypeReference;
  13. import org.springframework.http.HttpMethod;
  14. import org.springframework.http.ResponseEntity;
  15. import org.springframework.stereotype.Service;
  16. import org.springframework.web.client.RestTemplate;
  17. //在类上,增加@CacheConfig 注解,用来描述当前类型可能使用 cache 缓存。
  18. //如果使用缓存,则缓存数据的 key 的前缀是 cacheNames。
  19. //cacheNames 是用来定义一个缓存集的前缀命名的,相当于分组
  20. @CacheConfig(cacheNames = "test.hystrix.caches")
  21. @Service
  22. public class ClientServiceImpl implements ClientService {
  23. @Autowired
  24. private LoadBalancerClient loadBalancerClient;
  25. //@HystrixCommand - 开启 Hystrix 容错处理的注解。代表当前方法如果出现服务调用问题,使用 Hystrix 容错处理逻辑来处理
  26. //属性 fallbackMethod - 如果当前方法调用服务,远程服务出现问题的时候,调用本地的哪个方法得到托底数据。
  27. @HystrixCommand(fallbackMethod = "downgradeFallback",commandProperties = {
  28. // 默认 20 个;10s 内请求数大于 20 个时就启动熔断器,当请求符合熔断条件时将触发 fallback 逻辑
  29. @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, value = "10"),
  30. // 请求错误率大于 50%时就熔断,然后 for 循环发起请求,当请求符合熔断条件时将触发
  31. @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, value = "50"),
  32. // 默认 5 秒;熔断多少秒后去尝试请求
  33. @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value = "5000")
  34. }
  35. )
  36. @Override
  37. public String first() {
  38. ServiceInstance si = this.loadBalancerClient.choose("application-service");
  39. StringBuilder sb = new StringBuilder();
  40. sb.append("http://").append(si.getHost()).append(":").append(si.getPort()).append("/");
  41. System.out.println("本次访问的 service 是: " + sb.toString());
  42. RestTemplate rt = new RestTemplate();
  43. ParameterizedTypeReference<String> type = new ParameterizedTypeReference<String>() { };
  44. ResponseEntity<String> response = rt.exchange(sb.toString(), HttpMethod.GET, null, type);
  45. String result = response.getBody();
  46. return result;
  47. }
  48. //@Cacheable - 将当期方法的返回值缓存到 cache 中
  49. //只要方法增加了@Cacheable 注解,每次调用当前方法的时候,spring cloud 都会先访问 cache 获取数据
  50. //如果 cache 中没有数据,则访问远程服务获取数据。远程服务返回数据,先保存在 cache 中,再返回给客户端
  51. //如果 cache 中有数据,则直接返回 cache 中的数据,不会访问远程服务。
  52. //请求缓存会有缓存数据不一致的可能。缓存数据过期、失效、脏数据等情况。
  53. //一旦使用了请求缓存来处理幂等性请求操作。则在非幂等性请求操作中必须管理缓存。避免缓存数据的错误。
  54. @Override
  55. @Cacheable("myCache")
  56. public String testGet() {
  57. ServiceInstance si = this.loadBalancerClient.choose("application-service");
  58. StringBuilder sb = new StringBuilder();
  59. sb.append("http://").append(si.getHost()).append(":").append(si.getPort()).append("/testGet");
  60. System.out.println("本次访问的 service 是: " + sb.toString());
  61. RestTemplate rt = new RestTemplate();
  62. ParameterizedTypeReference<String> type = new ParameterizedTypeReference<String>() { };
  63. ResponseEntity<String> response = rt.exchange(sb.toString(), HttpMethod.GET, null, type);
  64. String result = response.getBody();
  65. return result;
  66. }
  67. //管理缓存。根据参数 key 删除缓存中对应的缓存数据
  68. @Override
  69. @CacheEvict("myCache")
  70. public String testPost() {
  71. ServiceInstance si = this.loadBalancerClient.choose("application-service");
  72. StringBuilder sb = new StringBuilder();
  73. sb.append("http://").append(si.getHost()).append(":").append(si.getPort()).append("/testPost");
  74. System.out.println("本次访问的 service 是: " + sb.toString());
  75. RestTemplate rt = new RestTemplate();
  76. ParameterizedTypeReference<String> type = new ParameterizedTypeReference<String>() { };
  77. ResponseEntity<String> response = rt.exchange(sb.toString(), HttpMethod.POST, null, type);
  78. String result = response.getBody();
  79. return result;
  80. }
  81. // 本地容错方法,只有远程服务调用过程出现问题的时候,才会调用此方法,获取托底数据。保证服务完整性。
  82. private String downgradeFallback(){
  83. return "服务降级方法返回托底数据";
  84. }
  85. }

4.4 application client 配置文件 application.yml

  1. server:
  2. port: 8082
  3. spring:
  4. application:
  5. name: application-client
  6. redis:
  7. host: 192.168.89.129
  8. eureka:
  9. client:
  10. service-url:
  11. defaultZone:
  12. - http://localhost:8761/eureka/
  13. hystrix:
  14. command:
  15. default: # default 全局有效,service id 指定应用有效,如:application-service
  16. execution:
  17. timeout:
  18. # 如果 enabled 设置为 false,则请求超时交给 ribbon 控制,为 true,则超时作为容错根据
  19. enabled: true
  20. isolation:
  21. thread:
  22. timeoutInMilliseconds: 1000 # 超时时间,默认 1000ms

4.5 application client 启动类

  1. package com.csdn;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cache.annotation.EnableCaching;
  5. import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
  6. //@EnableCircuitBreaker - 开启 Hystrix 容错处理能力。
  7. //如果不使用此注解,服务代码中的@HystrixCommand 注解无效
  8. //EnableCaching - 开启 spring cloud 对 cache 的支持
  9. //可以自动的使用请求缓存,访问 redis 等 cache 服务。
  10. @EnableCaching
  11. @SpringBootApplication
  12. @EnableCircuitBreaker
  13. public class ClientApp {
  14. public static void main(String[] args) {
  15. SpringApplication.run(ClientApp.class, args);
  16. }
  17. }

5.Openfeign 的雪崩处理

  • 在声明式远程服务调用 Openfeign 中,实现服务灾难性雪崩效应处理也是通过 Hystrix 实现的。
  • 而 feign 启动器 spring-cloud-starter-openfeign 中是包含 Hystrix 相关依赖的。如果只使用服务降级功能则不需要做独立依赖。如果需要使用 Hystrix 其他服务容错能力,需要依赖 spring-cloud-starter-netflix-hystrix 资源。
  • 从 Dalston 版本后,feign 默认关闭 Hystrix 支持。所以必须在全局配置文件中开启 feign 技术中的 Hystrix 支持。具体实现如下:

5.1 服务降级

5.1.1 POM 依赖
  • Openfeign 的启动器依赖 spring-cloud-starter-openfeign 中,自带 Hystrix 处理相关依赖,所以不需要修改 POM 依赖,直接通过配置即可开启容错处理机制。
5.1.2 application client 接口
  1. package com.csdn.service;
  2. import com.csdn.service.impl.FirstClientServiceImpl;
  3. import com.csdn.serviceapi.FirstServiceAPI;
  4. import org.springframework.cloud.openfeign.FeignClient;
  5. //注解属性 fallback - 当前接口远程调用服务发生问题时,使用哪一个对象中的对应方法用于实现容错逻辑
  6. //Openfeign 技术中,容错处理是使用当前接口的实现类实现的。
  7. //实现类中的方法实现,就是对应的容错 fallback 处理逻辑
  8. @FeignClient(name="openfeign-service", fallback = FirstClientServiceImpl.class)
  9. public interface FirstClientService extends FirstServiceAPI { }
5.1.3 application client 接口实现
  1. package com.csdn.service.impl;
  2. import com.csdn.entity.User;
  3. import com.csdn.service.FirstClientService;
  4. import org.springframework.stereotype.Component;
  5. import java.util.Arrays;
  6. import java.util.List;
  7. //当前类型的实例必须由 Spring 容器管理,需要使用@Component 注解描述。
  8. //每个实现方法对应远程服务调用的容错处理逻辑
  9. @Component
  10. public class FirstClientServiceImpl implements FirstClientService {
  11. @Override
  12. public List<String> testFeign() {
  13. return Arrays.asList("Openfeign 返回托底数据");
  14. }
  15. @Override
  16. public User getMultiParams(Integer id, String name) {
  17. User user = new User();
  18. user.setId(0);
  19. user.setUsername("托底数据");
  20. user.setRemark("getMultiParams");
  21. return user;
  22. }
  23. @Override
  24. public User postMultiParams(Integer id, String name) {
  25. User user = new User();
  26. user.setId(0);
  27. user.setUsername("托底数据");
  28. user.setRemark("postMultiParams");
  29. return user;
  30. }
  31. @Override
  32. public User postObjectParam(User pojo) {
  33. User user = new User();
  34. user.setId(0);
  35. user.setUsername("托底数据");
  36. user.setRemark("postObjectParam");
  37. return user;
  38. }
  39. }
5.1.4 application client 配置文件 application.yml
  1. server:
  2. port: 8082
  3. spring:
  4. application:
  5. name: openfeign-client
  6. eureka:
  7. client:
  8. service-url:
  9. - http://localhost:8761/eureka/
  10. feign: # 开启 feign 技术中的 Hystrix 容错处理机制
  11. hystrix:
  12. enabled: true
  13. hystrix:
  14. command:
  15. default:
  16. execution:
  17. timeout:
  18. enable: true
  19. isolation:
  20. thread:
  21. timeoutInMilliseconds: 1000
5.1.5 applicaiton client 启动类
  1. package com.csdn;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.openfeign.EnableFeignClients;
  5. // @EnableCircuitBreaker - 在 Openfeign 开发的 application client 应用的启动类中,不需要使用此注解开启容错处理逻辑。
  6. //Openfeign 的启动器 spring-cloud-starter-openfeign 中,依赖的是 Hystrix 相关 jar 包,不是完整的 spring-cloud-starter-netflix-hystrix 启动器。
  7. //如果使用此注解,在启动的时候,会抛出 ClassNotFoundException。
  8. @SpringBootApplication
  9. @EnableFeignClients(basePackages = "com.csdn.service")
  10. public class OpenfeignClientApp {
  11. public static void main(String[] args) {
  12. SpringApplication.run(OpenfeignClientApp.class, args);
  13. }
  14. }

5.2 服务熔断

  • 在 Openfeign 技术中,服务熔断对代码和依赖没有其他任何要求,只需要增加对应的配置即可,具体配置如下:
  1. server:
  2. port: 8082
  3. spring:
  4. application:
  5. name: openfeign-client
  6. eureka:
  7. client:
  8. service-url:
  9. - http://localhost:8761/eureka/
  10. feign:
  11. hystrix:
  12. enabled: true
  13. hystrix:
  14. command:
  15. default:
  16. execution:
  17. timeout:
  18. enable: true
  19. isolation:
  20. thread:
  21. timeoutInMilliseconds: 1000
  22. fallback:
  23. enabled: true # 当远程调用失败或者请求被拒绝,是否会尝试调用 fallback 方法 。默认 true
  24. circuitBreaker: # 服务熔断(Circuit Breaker)相关配置属性
  25. enabled: true # 是否开启熔断器。默认 true
  26. requestVolumeThreshold: 20 # 默认 20 个;10s 内请求数大于 20 个时就启动熔断器,当请求符合熔断条件时将触发 fallback 逻辑
  27. errorThresholdPercentage: 50 # 请求错误率大于 50%时就熔断,然后 for 循环发起请求,当请求符合熔断条件时将触发
  28. sleepWindowInMilliseconds: 5000 # 默认 5 秒;熔断多少秒后去尝试请求
  29. forceOpen: false # 是否强制打开熔断器, 默认 false
  30. forceClosed: false # 是否强制关闭熔断器, 默认 false

6.可视化的数据监控 Hystrix-dashboard

  • Hystrix Dashboard 是一款针对 Hystrix 进行实时监控的工具,通过 Hystrix Dashboard 我们可以在直观地看到各 Hystrix Command 的请求响应时间, 请求成功率等数据。
  • 具体开启方式如下:

6.1 POM 依赖

  • Hystrix Dashboard 是针对 Hystrix 容错处理相关数据的监控工具。只要在使用了 Hystrix 技术的应用工程中导入对应依赖即可。
  • 注意:如果在 Openfeign 技术中开启 Hystrix Dashboard 监控,则需要将 spring-cloud-starter-netflix-hystrix 启动器导入 POM 文件,否则无法在启动类上使用@EnableCircuitBreaker 注解。
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  5. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  6. <parent>
  7. <artifactId>cloudhystrix</artifactId>
  8. <groupId>com.csdn</groupId>
  9. <version>1.0-SNAPSHOT</version>
  10. </parent>
  11. <modelVersion>4.0.0</modelVersion>
  12. <artifactId>applicationclient</artifactId>
  13. <dependencies>
  14. <dependency>
  15. <groupId>org.springframework.boot</groupId>
  16. <artifactId>spring-boot-starter-web</artifactId>
  17. </dependency>
  18. <dependency>
  19. <groupId>org.springframework.cloud</groupId>
  20. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter-data-redis</artifactId>
  25. </dependency>
  26. <dependency>
  27. <groupId>org.springframework.cloud</groupId>
  28. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.springframework.boot</groupId>
  32. <artifactId>spring-boot-starter-actuator</artifactId>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.springframework.cloud</groupId>
  36. <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
  37. </dependency>
  38. </dependencies>
  39. </project>

6.2 配置文件 application.yml

  1. server:
  2. port: 8082
  3. spring:
  4. application:
  5. name: application-client
  6. redis:
  7. host: 192.168.89.129
  8. eureka:
  9. client:
  10. service-url:
  11. defaultZone:
  12. - http://localhost:8761/eureka/
  13. hystrix:
  14. command:
  15. default: # default 全局有效,service id 指定应用有效,如:application-service
  16. execution:
  17. timeout:
  18. # 如果 enabled 设置为 false,则请求超时交给 ribbon 控制,为 true,则超时作为容错根据
  19. enabled: true
  20. isolation:
  21. thread:
  22. timeoutInMilliseconds: 1000 # 超时时间,默认 1000ms
  23. management:
  24. endpoints:
  25. web:
  26. exposure:
  27. include: # 开启的 actuator 监控路径,默认开启 info 和 health。其他需要手工增加,使用*代表开启所有监控路径。
  28. - info
  29. - health
  30. - hystrix.stream

6.3 启动类

  1. package com.csdn;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cache.annotation.EnableCaching;
  5. import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
  6. import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
  7. //@EnableCircuitBreaker - 开启 Hystrix 容错处理能力。
  8. //如果不使用此注解,服务代码中的@HystrixCommand 注解无效。
  9. //且 Hystrix 相关监控数据无法收集。
  10. //@EnableCaching - 开启 spring cloud 对 cache 的支持。
  11. //可以自动的使用请求缓存,访问 redis 等 cache 服务
  12. //@EnableHystrixDashboard - 开启 Hystrix Dashboard 监控仪表盘
  13. @EnableHystrixDashboard
  14. @EnableCaching
  15. @SpringBootApplication
  16. @EnableCircuitBreaker
  17. public class ClientApp {
  18. public static void main(String[] args) {
  19. SpringApplication.run(ClientApp.class, args);
  20. }
  21. }

6.4 访问 Hystrix 监控数据

  • 通过浏览器访问提供监控访问路径的应用,具体地址为:
  • http://ip:port/actuator/hystrix.stream
  • 得到的监控结果如下:

  • 这种监控数据的获取都是 JSON 数据。且数据量级较大。不易于查看。可以使用 Hystrix Dashboard 提供的视图界面来观察监控结果。视图界面访问路径为: http://ip:port/hystrix。

  • 进入后的监控视图界面具体含义如下:

相关文章