转载

Spring Cloud (7) —— Hystrix 熔断、降级、隔离

关于 Hystrix

  1. 熔断

    • 熔断是 consumer 角色一侧的功能。
    • 当请求某一 provider 的失败情况达到某一阀值后,断路器会切换到 open 状态,请求将不再发往这个 provider 。
    • 断路器打开一段时间后,会切换到 half-open 状态,此时断路器的状态将取决于下一次请求是否成功。如果成功,则切换到 closed 状态;如果失败,则切换到 open 状态。
  2. 服务降级 Fallback
    当处理出现异常,或不具备处理能力时(负载过高、线程池用完),则会快速返回一个预先指定的值。
  3. 资源隔离
    资源隔离主要用来预防雪崩的发生,限制某一资源不可用引起的全局资源挂起。可选的隔离方式有 线程隔离、信号量隔离。

熔断 和 降级

在一般方法上应用

  1. 创建模块 spring-cloud.s05.store-hystrix
  2. pom 中添加依赖

    <dependencies>
        <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
      </dependencies>
  3. 添加配置文件

    server:
      port: 31003
    spring:
      application:
        name: store-hystrix
    eureka:
      client:
        serviceUrl:
          defaultZone: http://user:123123@localhost:34001/eureka/
      instance:
        instance-id: ${spring.cloud.client.ip-address}:${server.port}
        prefer-ip-address: true
        lease-renewal-interval-in-seconds: 10
        lease-expiration-duration-in-seconds: 30
    info:
      app.name: ${spring.application.name}
      compony.name: me.xhy
      build.artifactId: $project.artifactId$
      build.modelVersion: $project.modelVersion$
  4. 创建启动类 ..StoreHystrix

    @SpringBootApplication
    @EnableEurekaClient
    // 开启降级
    @EnableHystrix
    public class StoreHystrix {
    
      public static void main(String[] args) {
        SpringApplication.run(StoreHystrix.class, args);
      }
    
      @Bean
      @LoadBalanced
      RestTemplate restTemplate() {
        return new RestTemplate();
      }
    }

    如果启动类中 不写 @EnableHystrix 注解,那么当方法失败时,是不会执行降级方法的;但是注解了 @HystrixCommand 的方法是可以有熔断功能的,默认值也依然是 3次 , 当失败次数达到3次时,在 ribbon 中剔除该资源。

  5. 创建程序访问入口 ..ConsumerCircuitController

    @RestController
    @RequestMapping("/hystrix")
    public class CircuitFallbackController {
    
      @Autowired
      RestTemplate restTemplate;
    
      /*
      新增了 @HystrixCommand
      @HystrixCommand(fallbackMethod = "getMoviesError") 默认键为 fallbackMethod
      表示当调用 provider 失败,调用的补偿方法
      默认情况下,发生3次错误(补偿方法调用了3次),该 provider 将被熔断
      当被熔断的 provider 重新上线,将被重新加回到服务列表
      */
      @RequestMapping("/cf/ribbon")
      @HystrixCommand(fallbackMethod = "getServerPortError")
      public String getServerPort() {
        return restTemplate.getForObject("http://album-provider/album/server-port", String.class);
      }
    
      public String getServerPortError() {
        return "ribbon method getMovies occur hystrix";
      }
    
      @RequestMapping("/cf/always-exception")
      @HystrixCommand(fallbackMethod = "getServerPortError")
      public String alwaysException() {
        if(true) throw new RuntimeException();
        return "hi";
      }
    }

    这个 Controller 中有两个访问入口, @RequestMapping("/circuit/always-exception") 始终都会发生异常;@HystrixCommand(fallbackMethod = "getServerPortError") 则需要在正常访问所有 provider 后,停掉至少一个 provider 来观察结果。

  6. 验证熔断和降级

    http://localhost:31003/hystrix/circuit/always-exception
    http://localhost:31003/hystrix/circuit/ribbon
    

    启动类注解了 @EnableHystrix 服务降级才会生效。 @HystrixCommand 只有在应用 ribbon 的方法上,才会有熔断效果。

在 Feign 上应用

Feign 是自带断路器的,但是它没有默认打开。需要在配置文件中配置打开它

  1. pom 中引入 Feign

    <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
  2. 在配置文件中打开断路器

    feign:
      hystrix:
        enabled: true
  3. 启动类增加注解

    @EnableFeignClients // Feign 需要
  4. 创建 Feign 接口

    @FeignClient(value = "album-provider", fallback = CircuitFallbackFeignServiceFallback.class)
    public interface CircuitFallbackFeignService {
    
      @RequestMapping("/album/server-port")
      String getServerPort();
    
    }
    
    /*
    该类提供发生异常时的补偿方法
    必须要有 @Component , 可以是外部类
     */
    @Component
    class CircuitFallbackFeignServiceFallback implements CircuitFallbackFeignService {
      @Override
      public String getServerPort() {
        return "feign method getServerPort occur hystrix";
      }
    }
  5. 创建访问程序入口 ..CircuitFallbackFeignController

    @RestController
    @RequestMapping("/hystrix")
    public class CircuitFallbackFeignController {
    
      @Autowired
      CircuitFallbackFeignService service;
    
      @RequestMapping("/cf/feign")
      public String getServerPort() {
        return service.getServerPort();
      }
    }
  6. 访问 http://localhost:31003/hystrix/cf/feign

    如果配置文件中不开启断路器,降级方法是不会执行的

隔离

隔离可以防止雪崩的出现。当 provider 没有足够的处理能力时, consumer 的请求无法返回导致线程挂起,逐层影响,最终雪崩。如果限制 consumer 请求某个 provider 的 , consumer 就不会因为 provider 丧失处理能力而挂起过多的线程, consumer 仍然可以保持服务能力,去做其他任务。

使用线程隔离

使用信号量隔离

原文  https://segmentfault.com/a/1190000022235933
正文到此结束
Loading...