• Hystrix使用篇 - Hystrix的使用


    前言

    Hystrix,[hɪst’rɪks]

    Hystrix 是一个延迟和容错库,旨在隔离远程系统、服务和第三方库,阻止级联故障,在复杂的分布式系统中实现恢复能力。

    Hystrix is a latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable.

    Hystrix的设计目标

    1、通过客户端库对延迟和故障进行保护和控制。

    2、在一个复杂的分布式系统中停止级联故障。

    3、快速失败和快速恢复。

    4、在合理的情况下回退和优雅降级。

    5、开启近实时监控、告警和操作控制。

    Hystrix的降级策略

    Hystrix提供了如下三种降级策略:Hystrix参数说明

    • 熔断降级

      默认在10秒内,发送20次请求,失败率达到50%,就会触发熔断降级。

    • 超时降级

      默认请求的响应时间超过1秒,就会触发超时降级。

    • 资源隔离降级

      资源隔离分为信号量隔离和线程池隔离。

      • 信号量隔离

        调用线程与hystrixCommand线程是同一个线程。同步方式。资源消耗小。不支持超时。

      • 线程池隔离

        调用线程与hystrixCommand线程不是同一个线程。异步方式。支持超时。可以为每个服务单独分配线程池。大量线程的上下文切换带来的开销比较大。

    Hystrix全局配置

    @HystrixCommand注解的配置优先于Hystrix全局配置

    hystrix:
        command:
            default:
                circuitBreaker:
                    enabled: true
                    requestVolumeThreshold: 20
                    errorThresholdPercentage: 50
                    sleepWindowInMilliseconds: 5000
                execution:
                    timeout:
                        enabled: true
                    isolation:
                        thread:
                            timeoutInMilliseconds: 2000
                            interruptOnTimeout: true
                        semaphore:
                            maxConcurrentRequests: 10
                        strategy: THREAD
                metrics:
                    rollingStats:
                        timeInMilliseconds: 10000
        threadpool:
            default:
                coreSize: 10
                maximumSize: 19
                allowMaximumSizeToDivergeFromCoreSize: false
                keepAliveTimeMinutes: 1
                maxQueueSize: -1
                queueSizeRejectionThreshold: 5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    代码演示1、Hystrix

    1、 首先在 pom.xml 中导入如下依赖:

    <dependency>
      <groupId>org.springframework.cloudgroupId>
      <artifactId>spring-cloud-starter-netflix-hystrixartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    2、启动类添加 @EnableCircuitBreaker 注解或者 @EnableHystrix 注解

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

    3、准备HystrixService以及实现类HystrixServiceImpl

    HystrixService

    public interface HystrixService {
    
        String hystrixMethod(String name);
    }
    
    • 1
    • 2
    • 3
    • 4

    HystrixServiceImpl

    @Service
    public class HystrixServiceImpl implements HystrixService {
    
        @Autowired
        private RestTemplate restTemplate;
    
        @Override
        public String hystrixMethod(String name) {
            return restTemplate.getForObject("http://localhost:8081/order/orders", String.class);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4.1、熔断触发降级演示

    HystrixController

    @RestController
    @RequestMapping("hystrix")
    public class HystrixController {
    
        @Autowired
        private HystrixService hystrixService;
    
        @GetMapping("{num}")
        @HystrixCommand(fallbackMethod = "circuitBreakerFallback", commandProperties = {
                @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ENABLED, value = "true"),
                @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, value = "20"),
                @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, value = "50"),
                @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value = "5000"),
                @HystrixProperty(name = HystrixPropertiesManager.METRICS_ROLLING_STATS_TIME_IN_MILLISECONDS, value = "10000")
        })
        public String testCircuitBreaker(@PathVariable Integer num, @RequestParam String name) {
            if (num % 2 == 0) {
                return "请求成功";
            }
            return hystrixService.hystrixMethod(name);
        }
    
      	// fallback方法的参数个数、参数类型、返回值类型要与原方法对应,fallback方法的参数多加个Throwable
        public String circuitBreakerFallback(Integer num, String name) {
            return "请求失败,请稍后重试";
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    circuitBreaker.enabled:是否开启断路器,默认true

    circuitBreaker.requestVolumeThreshold:请求数量的阈值,默认20

    circuitBreaker.errorThresholdPercentage:失败的比例阈值,默认50

    circuitBreaker.sleepWindowInMilliseconds:熔断的时长,默认5000

    metrics.rollingStats.timeInMilliseconds:统计的时间窗口的时间段大小,默认10000

    实际结果:不启动order服务对应的应用的情况下,先请求 http://localhost:8080/hystrix/2?name=tom,得到的是“请求成功”;接着请求 http://localhost:8080/hystrix/1?name=tom,得到的是“请求失败,请稍后重试”,当触发熔断时,这时请求 http://localhost:8080/hystrix/2?name=tom,得到的却是“请求失败,请稍后重试”,过了熔断的时长5秒后,再次请求 http://localhost:8080/hystrix/2?name=tom,发现得到的是“请求成功”。

    4.2、超时触发降级演示

    @RestController
    @RequestMapping("hystrix")
    public class HystrixController {
    
        @Autowired
        private HystrixService hystrixService;
    
        @GetMapping
        @HystrixCommand(fallbackMethod = "timeoutFallback", commandProperties = {
                @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_TIMEOUT_ENABLED, value = "true"),
                @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS, value = "10000"),
                @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_THREAD_INTERRUPT_ON_TIMEOUT, value = "true")
        })
        public String testTimeout(@RequestParam String name) {
            return hystrixService.hystrixMethod(name);
        }
    
        public String timeoutFallback(String name) {
            return "请求超时,请稍后重试";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    execution.timeout.enabled:是否开启请求超时,默认true

    execution.isolation.thread.timeoutInMilliseconds:请求的超时时间,默认10000

    execution.isolation.thread.interruptOnTimeout:当请求超时时,是否中断线程,默认true

    启动Order应用

    @RestController
    public class OrderServiceImpl implements OrderService {
    
        @Value("${server.port}")
        private Integer port;
    
        @Override
        public String orders() {
            try {
              	// 设置睡眠2秒
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return String.valueOf(port);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    实际结果:请求 http://localhost:8080/hystrix?name=tom ,得到的是“请求超时,请稍后重试”。如果去掉Order应用的睡眠2秒的代码,则得到的是“8081”,即Order应用对应的服务返回的结果。

    4.3、资源隔离(线程池)触发降级

    @RestController
    @RequestMapping("hystrix")
    public class HystrixController {
    
        @Autowired
        private HystrixService hystrixService;
    
        @GetMapping("isolation/threadpool")
        @HystrixCommand(fallbackMethod = "isolationFallback",
                commandProperties = {
                   		@HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY, value = "THREAD")
                },
                threadPoolProperties = {
                        @HystrixProperty(name = HystrixPropertiesManager.CORE_SIZE, value = "10"),
                        @HystrixProperty(name = HystrixPropertiesManager.MAX_QUEUE_SIZE, value = "-1"),
                        @HystrixProperty(name = HystrixPropertiesManager.QUEUE_SIZE_REJECTION_THRESHOLD, value = "2"),
                        @HystrixProperty(name = HystrixPropertiesManager.KEEP_ALIVE_TIME_MINUTES, value = "1"),
                }
        )
        public String testThreadPoolIsolation(@RequestParam String name) {
            return hystrixService.hystrixMethod(name);
        }
    
        public String isolationFallback(String name) {
            return "资源隔离拒绝,请稍后重试";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    execution.isolation.strategy:资源隔离策略,支持THREAD、SEMAPHORE。默认THREAD

    coreSize:线程池的核心线程数,默认10

    maximumSize:线程池的最大线程数,默认10(实际在操作中无法识别该属性,待后期版本验证)

    allowMaximumSizeToDivergeFromCoreSize:是否使maximumSize参数生效,默认false(实际在操作中无法识别该属性,待后期版本验证)

    maxQueueSize:默认-1(如果是-1,则线程池的内部的队列使用SynchronousQueue,否则使用LinkedBlockingQueue)

    keepAliveTimeMinutes:线程池中的线程的生存时间(单位:分钟),默认1

    queueSizeRejectionThreshold:线程池中的队列长度达到多少就可以拒绝添加任务,即使队列长度没有达到 maxQueueSize。因为阻塞队列的maxQueueSize不能动态调整,所以引用这个参数来动态调整拒绝任务时的队列长度。默认5。

    启动Order应用

    @RestController
    public class OrderServiceImpl implements OrderService {
    
        @Value("${server.port}")
        private Integer port;
    
        @Override
        public String orders() {
            try {
              	// 设置睡眠2秒
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return String.valueOf(port);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    4.4、资源隔离(信号量)触发降级

    @RestController
    @RequestMapping("hystrix")
    public class HystrixController {
    
        @Autowired
        private HystrixService hystrixService;
    
        @GetMapping("isolation/semaphore")
        @HystrixCommand(fallbackMethod = "isolationFallback",
                commandProperties = {
                        @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY, value = "SEMAPHORE"),
                        @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS, value = "2")
                }
        )
        public String testSemaphoreIsolation(@RequestParam String name) {
            return hystrixService.hystrixMethod(name);
        }
    
        public String isolationFallback(String name) {
            return "资源隔离拒绝,请稍后重试";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    execution.isolation.strategy:资源隔离策略,支持THREAD、SEMAPHORE。默认THREAD

    execution.isolation.semaphore.maxConcurrentRequests:信号量隔离中的最大并发请求数,默认10

    启动Order应用

    @RestController
    public class OrderServiceImpl implements OrderService {
    
        @Value("${server.port}")
        private Integer port;
    
        @Override
        public String orders() {
            try {
              	// 设置睡眠2秒
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return String.valueOf(port);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    代码演示2、Hystrix+Open Feign

    在服务提供方定义 feign client 接口 以及 fallback,在服务消费方定义具体的降级策略。

    一、Order服务

    OrderService

    @RequestMapping("order")
    public interface OrderService {
      
      @GetMapping("orders")
      String orders();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    OrderServiceImpl

    @RestController
    public class OrderServiceImpl implements OrderService {
      
      @Value("${server.port}")
      private Integer port;
      
      @Override
      public String orders() {
        try {
          Thread.sleep(2000);
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt():
        }
        return String.valueOf(port);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    OrderServiceFeignClient

    @FeignClient(value = "spring-cloud-order", fallback = OrderServiceFallback.class)
    public interface OrderServiceFeignClient extends OrderService {
      
    }
    
    • 1
    • 2
    • 3
    • 4

    OrderServiceFallback

    public class OrderServiceFallback implements OrderServiceFeignClient {
      
      @GetMapping("orders")
      @Override
      public String orders() {
        return "系统繁忙,请稍后重试";
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    二、User服务

    UserController

    @RestController
    @RequestMapping("user")
    public class UserController {
      
      @Resource
      private OrderServiceFeignClient orderServiceFeignClient;
      
      @GetMapping("orders")
      pubic String orders() {
        return orderServiceFeignClient.orders();
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    SpringCloudUserApplication

    @SpringBootApplication(scanBasePackages = {
      "com.mzs.springcloud.user"
      "com.mzs.order.api.fallback"	// order服务fallback的包路径
    })
    @EnableFeignClients(basePackages = {
      "com.mzs.order.api.clients"		// order服务feign client的包路径
    })
    @EnableCircuitBreaker
    public class SpringCloudUserApplication {
      
      public static void main(String[] args) {
        SpringApplication.run(SpringCloudUserApplication.class, args);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    application.yml

    feign:
        hystrix:
            enabled: true
    
    hystrix:
        command:
            default:
                circuitBreaker:
                    enabled: true
                    requestVolumeThreshold: 20
                    errorThresholdPercentage: 50
                    sleepWindowInMilliseconds: 5000
                execution:
                    timeout:
                        enabled: true
                    isolation:
                        thread:
                            timeoutInMilliseconds: 1000
                            interruptOnTimeout: true
                        semaphore:
                            maxConcurrentRequests: 10
                        strategy: THREAD
                metrics:
                    rollingStats:
                        timeInMilliseconds: 10000
            OrderServiceFeignClient#orders():
                execution:
                    timeout:
                        enabled: true
                    isolation:
                        thread:
                            timeoutInMilliseconds: 3000
                            interruptOnTimeout: true
        threadpool:
            default:
                coreSize: 10
                maximumSize: 10
                allowMaximumSizeToDivergeFromCoreSize: false
                keepAliveTimeMinutes: 1
                maxQueueSize: -1
                queueSizeRejectionThreshold: 5
            spring-cloud-order:
                coreSize: 10
                maximumSize: 10
                allowMaximumSizeToDivergeFromCoreSize: false
                keepAliveTimeMinutes: 1
                maxQueueSize: -1
                queueSizeRejectionThreshold: 10
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    代码演示3、Hystrix Dashboard

    pom.xml

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

    application.yml

    server:
    	port: 8080
    
    management:
      endpoints:
        web:
          exposure:
            include: hystrix.stream
            
    hystrix:
    	 dashboard:
            proxy-stream-allow-list: 192.168.124.3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    此外,启动类加 @EnableHystrixDashboard 注解。然后在浏览器地址输入 http://192.168.124.3:8080/hystrix,进入 Hystrix Dashboard 的页面。

    在这里插入图片描述

    输入 https://192.168.124.3:8080/actuator/hystrix.stream,然后点击 Monitor Stream 按钮。

    在这里插入图片描述

    代码演示4、Turbine

    在代码演示三的基础上增加如下:

    pom.xml

    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-turbineartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    application.yml

    turbine:
        app-config: spring-cloud-user,spring-cloud-order
        cluster-name-expression: "'default'"
        aggregator:
            cluster-config: default
    
    • 1
    • 2
    • 3
    • 4
    • 5

    启动类额外增加 @EnableTurbine 注解。然后在浏览器地址输入 http://192.168.124.3:8080/hystrix,进入 Hystrix Dashboard 的页面。

    在这里插入图片描述

    输入 https://192.168.124.3:8080/actuator/turbine.stream,然后点击 Monitor Stream 按钮。

    在这里插入图片描述

  • 相关阅读:
    JAVA毕业设计教师教学质量评估系统计算机源码+lw文档+系统+调试部署+数据库
    go-micro使用Consul做服务发现的方法和原理
    为什么要学C语言及C语言存在的意义
    java计算机毕业设计高校多媒体设备运维管理系统服务端MyBatis+系统+LW文档+源码+调试部署
    Spring Ioc源码分析系列--Bean实例化过程(一)
    Linux基础 - Web服务基础
    Linux之bind 函数(详细篇)
    【每日一题】657. 机器人能否返回原点
    电商平台API接口亚马逊国际站获得AMAZON商品详情操作案例
    Python基础-4-操作列表
  • 原文地址:https://blog.csdn.net/qq_34561892/article/details/128022263