文章目录

  • 一、Hystrix应用场景
  • 二、Hystrix简单使用
  • 1.服务降级---生产者
  • 2.服务降级---消费者
  • 1.控制类中针对每个特定的方法做服务降级
  • 2.控制类中做统一的服务降级
  • 3.在Feign接口服务层做服务降级
  • 3.服务熔断---生产者
  • 1.服务熔断概述
  • 2.服务熔断的三种状态
  • 3.服务熔断的详细代码与效果
  • 4.断路器的三个重要参数
  • 3.服务监控---Hystrix Dashboard
  • Hystrix Dashboard 报错:Unable to connect to Command Metric Stream.



在微服务中,服务与服务之间通过远程方法调用,很有可能出现网络异常、服务自身错误等导致服务不可用,甚至由于服务之间的互相依赖,导致服务级联故障,形成服务雪崩。为了解决这个问题,引入了Spring Cloud Hystrix.

一、Hystrix应用场景

1. 服务降级(Fallback):
当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作

出现场景:

  • 程序运行异常
  • 超时
  • 服务熔断触发服务降级
  • 线程池/信号量打满触发服务降级

2. 服务熔断(Break):
服务熔断一般是指软件系统中,由于某些原因使得服务出现了过载现象,为防止造成整个系统故障,从而采用的一种保护措施,所以很多地方把熔断亦称为过载保护。服务熔断是建立在服务降级的基础上的,类似于SpringCloud建立在SpringBoot的基础上。
3. 服务限流(Flow Limit):
服务限流主要是提前对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。

二、Hystrix简单使用

1.服务降级—生产者
  1. 导入依赖
<dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
       </dependency>
  1. 在提供服务的service方法上加上 @HystrixCommand(fallbackMethod = "处理降级的方法")注解
@Service
public class HystrixService {
   /**
    * 服务降级
    */
   @HystrixCommand(fallbackMethod = "requestErrorHandler")
   public String requestError() {
       int a = 10 / 0;  //这里将抛出异常,触发服务降级
       return "request Error" + a;
   }

   /**
    *触发服务降级后执行此方法
    */
   public String requestErrorHandler() {
       return "CLOUD-PAYMENT-HYSTRIX-SERVICE:8004:request Error fallback";
   }
}
  1. 主启动类上添加@EnableCircuitBreaker注解
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class OrderHystrixMain8084 {
   public static void main(String[] args) {
       SpringApplication.run(OrderHystrixMain8084.class, args);
   }
}

可以看到我们访问直接访问这个服务,触发了服务降级,调用了服务降级对应的处理方法。

容器跑多少微服务 微服务容灾_微服务

2.服务降级—消费者

在生产者和消费者端都可以做服务降级,但是在消费者端做服务降级更加灵活,对于生产者端挂掉了也能做出相应处理,所以一般推荐在消费者端做服务降级.

下面的操作也需要导入依赖和在启动类上加上@EnableCircuitBreaker注解,就不都提了

1.控制类中针对每个特定的方法做服务降级

步骤:添加@HystrixCommand()注解并指明服务降级对应的处理方法

@RestController
@RequestMapping("/consumer/hystrix")
public class FeignOrderController {

    @Resource
    private OpenFeignOrderService feignOrderService;
    
    //为getError方法做服务降级,对应服务降级方法为requestErrorHandler
    @HystrixCommand(fallbackMethod = "requestErrorHandlreer")
    @GetMapping("/error")
    public CommonResult getError() {
        int a = 10 / 0; //这里将抛出异常,触发服务降级
        return feignOrderService.getError();
    }
    
    //服务降级处理
    public CommonResult requestErrorHandler() {
        return new CommonResult(500, "CLOUD-ORDER-FEIGN-HYSTRIX-SERVICE:80:request Error fallback", null);
    }
}
2.控制类中做统一的服务降级

但我们有很多方法时,每个都要指明对应的服务降级处理方法(代码膨胀),是很麻烦的事。比如访问哪个方法都可能出现访问超时的异常,可以都由同一个服务降级方法进行处理。所以统一的服务降级处理是很有必要的。

步骤:在控制类上添加@DefaultProperties(defaultFallback = "统一的服务降级处理方法"),在需要服务降级的方法上加上@HystrixCommand注解

@RestController
@RequestMapping("/consumer/hystrix")
//统一的服务降级处理
@DefaultProperties(defaultFallback = "requestGlobeErrorHandler")
public class FeignOrderController {

    @Resource
    private OpenFeignOrderService feignOrderService;
    
    @HystrixCommand
    @GetMapping("/globe/error")
    public CommonResult getGlobeError() {
        int a = 10 / 0;
        return feignOrderService.getError();
    }
    public CommonResult requestGlobeErrorHandler() {
        return new CommonResult(500, "CLOUD-ORDER-FEIGN-HYSTRIX-SERVICE:80:request Globe Error fallback", null);
    }
}
3.在Feign接口服务层做服务降级

之前的两种服务降级的方法,写在控制类中,与业务逻辑混在一起(代码混乱),耦合度高。但是通过Feign接口层进行调用时又不能实例化。解决方法就是新建一个服务降级类并实现FeignService层的方法.

步骤:Feign接口层指定fallback类,fallback类实现Feign接口方法,编写服务降级后处理逻辑。

OpenFeignOrderService.java

@Service
@FeignClient(value = "CLOUD-PAYMENT-HYSTRIX-SERVICE", fallback = OpenFeignOrderServiceFallback.class)
public interface OpenFeignOrderService {

    @GetMapping("/hystrix/ok")
    CommonResult getOk();

    @GetMapping("/hystrix/error")
    CommonResult getError();
}

OpenFeignOrderServiceFallback.java

@Component
public class OpenFeignOrderServiceFallback implements OpenFeignOrderService {

    @Override
    public CommonResult getOk() {
        return new CommonResult(500, "CLOUD-ORDER-FEIGN-HYSTRIX-SERVICE:80:request Error fallback by fallback class", null);

    }

    @Override
    public CommonResult getError() {
        return new CommonResult(500, "CLOUD-ORDER-FEIGN-HYSTRIX-SERVICE:80:request Error fallback by fallback class", null);
    }
}
3.服务熔断—生产者
1.服务熔断概述

容器跑多少微服务 微服务容灾_微服务_02

2.服务熔断的三种状态

容器跑多少微服务 微服务容灾_容器跑多少微服务_03

3.服务熔断的详细代码与效果
@Service
public class HystrixService {
  /**
   * 服务熔断:在10秒窗口期中10次请求有6次是请求失败的,断路器将起作用
   */
  @HystrixCommand(fallbackMethod = "requestBreakHandler", commandProperties = {
          @HystrixProperty(name = "circuitBreaker.enabled", value = "true"), //是否开启断路器
          @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), //请求次数
          @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "1000"), //时间窗口期
          @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"),//失败率达到多少后跳闸
  })
  public String requestBreak(int id) {
      int a = 10 / id;   
      return "test break: " + a;
  }

  /***
   *触发服务熔断后执行此方法
   */
  public String requestBreakHandler(int id) {
      return "CLOUD-PAYMENT-HYSTRIX-SERVICE:8004:request Error Break:" + id;
  }
}

咋一看,服务熔断和服务降级的代码差不多,无非多了几个@HystrixProperty属性(可在HystrixCommandProperties.java中查看所有属性),但是如果你触发服务熔断(在10秒窗口期中10次请求有6次是请求失败的),断路器起作用,进入熔断打开状态后,即使你访问的是正常的请求,也会进入熔断处理方法,过一会才会自动恢复.

4.断路器的三个重要参数

容器跑多少微服务 微服务容灾_java_04

3.服务监控—Hystrix Dashboard

Hystrix Dashboard 启动的端口:9001 被监控服务启动端口:8084

  1. 导入依赖:

Hystrix Dashboard(9001)导入依赖:

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

被监控服务(8084)导入依赖:

<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>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-actuator</artifactId>
      </dependency>
  1. Hystrix Dashboard(9001)启动类上增加@EnableHystrixDashboard注解
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashBoard9001 {
  public static void main(String[] args) {
      SpringApplication.run(HystrixDashBoard9001.class, args);
  }
}
  1. 访问http://localhost:9001/hystrix可以看到如下画面
  2. 输入框中输入需要监控的服务实例地址http://localhost:8084/actuator/hystrix.stream,点击Monitor Stream按钮.
Hystrix Dashboard 报错:Unable to connect to Command Metric Stream.

恭喜你,肯定会报错😄:Unable to connect to Command Metric Stream.

容器跑多少微服务 微服务容灾_java_05

原因:被监控的服务实例(8084)的EndPoint /actuator/hystrix.stream没有暴露出来,你可以通过访问 http://localhost:8084/actuator/hystrix.stream来验证,一定是404.

解决方法:

  • 方法一(推荐):修改被监控的服务实例(8084)的yml文件
management:
  endpoints:
    web:
      exposure:
        include: hystrix.stream
  • 方法二:被监控的服务实例(8084)的启动类中增加一个Servlet,修改映射
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class OrderHystrixMain8084 {
    public static void main(String[] args) {
        SpringApplication.run(OrderHystrixMain8084.class, args);
    }
    
    /**
     * 此配置是为了服务监控而配置,与服务器容错本身无关,springcloud升级后的坑
     * ServletRegistrationBean因为springboot的默认路径不是/hystrix.stream
     * 只要在自己的项目里配置上下文的servlet就可以了
     */
    @Bean
    public ServletRegistrationBean getservlet(){
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean<HystrixMetricsStreamServlet> registrationBean = new ServletRegistrationBean<>(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}