【Hoxton.SR1版本】Spring Cloud Hystrix断路器

SpringCloud 专栏收录该内容
33 篇文章 1 订阅

目录

一、简介

二、Hystrix重要概念

三、服务提供方Hystrix降级

四、服务消费方Hystrix降级

五、存在问题分析以及解决方法

六、服务熔断

七、Hystrix Dashboard仪表盘监控

八、总结


一、简介

我们都知道,复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败,如果服务调用的链路太长,当服务提供者出现不可用时,会将故障逐渐蔓延到服务消费者身上,这其实就是“雪崩效应”。

  • 雪崩效应

“雪崩效应”:因 '服务提供者' 的不可用导致 '服务调用者' 的不可用,并将不可用逐渐放大的过程。多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃。

对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。所以,通常当你发现一个模块的某个实例失败后,这时候这个模块依然还会接收流量,然后这个有问题的模块还调用了其他的模块,这样就会发生级联故障,或者叫雪崩。

  • Hystrix是什么?

Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免地会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出现问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性

“断路器”本身就是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(Fallback),而不是长时间的等待或者抛出调用方无法处理的异常,这样就是保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

  • Hystrix能干嘛?
  1. 服务降级
  2. 服务熔断
  3. 接近实时的监控
  4. .....

Hystrix官网学习资料:https://github.com/Netflix/Hystrix/wiki/How-To-Use

二、Hystrix重要概念

  • 服务降级

服务器忙,请稍后重试,不让客户端等待并立刻返回一个友好提示(Fallback失败回调)。

以下情况会触发服务降级:

  1. 程序运行异常;
  2. 超时;
  3. 服务熔断触发服务降级;
  4. 线程池/信号量打满也会导致服务降级;
  • 服务熔断

类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示。

  • 服务限流

秒杀高并发等操作,禁止一窝蜂地过来拥挤,大家排队,一秒钟N个,有序进行。

三、服务提供方Hystrix降级

下面我们新建一个module:Hystrix服务提供者微服务:【springcloud-provider-hystrix-payment8001】

【a】pom.xml:引入spring-cloud-starter-netflix-hystrix断路器模块

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud2020</artifactId>
        <groupId>com.wsh.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-provider-hystrix-payment8001</artifactId>

    <dependencies>
        <!--hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--web-->
        <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>
        <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
            <groupId>com.wsh.springcloud</groupId>
            <artifactId>springcloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
    </dependencies>


</project>

【b】application.yml配置文件

server:
  port: 8001
spring:
  application:
    name: springcloud-provider-hystrix-payment
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://springcloud-eureka7001.com:7001/eureka/,http://springcloud-eureka7002.com:7002/eureka/   #集群版Eureka注册中心

【c】主启动类加上注解@EnableCircuitBreaker开启断路器功能

package com.wsh.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
//@EnableCircuitBreaker开启Hystrix断路器功能
@EnableCircuitBreaker
public class HystrixPaymentServiceApplication8001 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixPaymentServiceApplication8001.class, args);
    }
}

【d】业务层Service接口

package com.wsh.springcloud.service;

import cn.hutool.core.util.IdUtil;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.concurrent.TimeUnit;

@Service
public class PaymentService {

    public String paymentInfoSuccess(Integer id) {
        return "线程名称:  " + Thread.currentThread().getName() + ">>>>id:  " + id;
    }

    /**
     * HystrixCommand注解主要开启熔断器的功能,并指定fallbackMethod熔断方法(服务不可用时执行熔断方法)
     * fallbackMethod: 指定服务降级方法
     * commandProperties: 指定断路器属性,如下配置在三秒内正常访问,超过三秒将会执行降级方法paymentInfoFailFallback
     * 说明:服务提供方降级处理,设置自身调用超时时间的峰值,峰值内可以正常运行,超过了需要有降级方法处理,做服务降级Fallback
     *
     */
    @HystrixCommand(fallbackMethod = "paymentInfoFailFallback", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
    })
    public String paymentInfoFail(Integer id) {
        try {
            TimeUnit.MILLISECONDS.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "线程名称:  " + Thread.currentThread().getName() + ">>>>id:  " + id;
    }

    /**
     * Hystrix熔断方法(即调用失败回调方法)
     */
    public String paymentInfoFailFallback(Integer id) {
       return  "sorry,[ " + id + "], the hystrix payment service is not available! ";
    }
    
}

【e】控制层接口

package com.wsh.springcloud.controller;

import com.wsh.springcloud.service.PaymentService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class PaymentController {
    @Resource
    private PaymentService paymentService;

    @GetMapping("/payment/hystrix/success/{id}")
    public String paymentInfoSuccess(@PathVariable("id") Integer id) {
        return paymentService.paymentInfoSuccess(id);
    }

    @GetMapping("/payment/hystrix/fail/{id}")
    public String paymentInfoFail(@PathVariable("id") Integer id) {
        return paymentService.paymentInfoFail(id);
    }

}

【f】测试

启动【springcloud-provider-hystrix-payment8001】,测试看下当业务处理时间超过设置的峰值时,是否会执行@HystrixCommand>>>>>fallbackMethod指定的降级方法。浏览器访问:http://localhost:8001/payment/hystrix/fail/100

由上图可知,当接口方法超过设置的超时时间峰值时,将会触发服务降级。

注意:超时或者接口方法内抛出异常(如空指针、算术运算异常等)也会导致服务走降级方法。 

以上是关于在服务提供方做的一些Hystrix降级处理,在实际项目中,我们比较常用的是在服务消费方做Hystrix降级处理,下面我们一起看下在服务消费方如何做降级处理。

四、服务消费方Hystrix降级

下面我们新建另外一个module:Hystrix服务消费者微服务:【springcloud-provider-hystrix-payment8001】

【a】pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud2020</artifactId>
        <groupId>com.wsh.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-consumer-feign-hystrix-order80</artifactId>

    <dependencies>
        <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>com.wsh.springcloud</groupId>
            <artifactId>springcloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--web-->
        <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>
        <!--一般基础通用配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

【b】application.yml配置文件:注意添加

feign:
  hystrix:
    enabled: true
server:
  port: 80
eureka:
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://springcloud-eureka7001.com:7001/eureka/,http://springcloud-eureka7002.com:7002/eureka/   #集群版Eureka注册中心
#开启Feign断路器功能
feign:
  hystrix:
    enabled: true

【c】主启动类添加注解@EnableHystrix

package com.wsh.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
//开启远程服务调用功能
@EnableFeignClients
//开启Hystrix断路器功能
@EnableHystrix
public class OrderHystrixServiceApplication80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderHystrixServiceApplication80.class, args);
    }
}

【d】定义Feign远程调用类:定义两个接口用于调用前面我们创建的Hystrix服务提供者微服务:【springcloud-provider-hystrix-payment8001】中的接口

package com.wsh.springcloud.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @Description 远程服务调用接口
 * @Date 2020/8/16 16:06
 * @Author weishihuai
 * 说明:
 */
@Component
//fallback:指定失败回调类
@FeignClient(value = "SPRINGCLOUD-PROVIDER-HYSTRIX-PAYMENT")
public interface PaymentHystrixFeignClient {

    @GetMapping("/payment/hystrix/success/{id}")
    String paymentInfoSuccess(@PathVariable("id") Integer id);

    @GetMapping("/payment/hystrix/fail/{id}")
    String paymentInfoFail(@PathVariable("id") Integer id);
}

【e】测试Controller类OrderHystrixController.java

package com.wsh.springcloud.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.wsh.springcloud.feign.PaymentHystrixFeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class OrderHystrixController {
    @Resource
    private PaymentHystrixFeignClient paymentHystrixFeignClient;

    @GetMapping("/consumer/payment/hystrix/success/{id}")
    public String paymentInfoSuccess(@PathVariable("id") Integer id) {
        return paymentHystrixFeignClient.paymentInfoSuccess(id);
    }

    @GetMapping("/consumer/payment/hystrix/fail/{id}")
    @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
    })
    public String paymentInfoFail(@PathVariable("id") Integer id) {
        return paymentHystrixFeignClient.paymentInfoFail(id);
    }

    public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id) {
        return "sorry,[" + id + "], the payment service is not available! ";
    }

}

可以看到,我们同样使用@HystrixCommand指定的降级方法和超时时间的峰值为1500毫秒,表示调用此接口我只愿意等1.5秒,如果1.5秒还没有返回数据,那么我不再等待,直接进入对应的降级方法。

【f】测试客户端的服务降级

在测试之前,我们首先修改一下【springcloud-provider-hystrix-payment8001】微服务中之前中接口的超时时间:

我们启动Eureka、 【springcloud-provider-hystrix-payment8001】、【springcloud-consumer-feign-hystrix-order80】微服务,然后我们浏览器访问:http://localhost/consumer/payment/hystrix/fail/100,运行结果如下图:

可见,服务消费方【springcloud-consumer-feign-hystrix-order80】也支持了服务降级,执行了我们指定的降级方法。

原因分析:服务提供方【springcloud-provider-hystrix-payment8001】中超时时间峰值是5秒钟,业务处理3秒钟,这肯定是没有问题的,服务提供方肯定不会超时;服务消费方【springcloud-consumer-feign-hystrix-order80】中超时时间峰值我们设置的是1.5秒,而服务提供者业务处理需要3秒钟,那么还没等到业务执行完,服务消费方只愿意等你1.5秒,那么就会触发超时降级方paymentTimeOutFallbackMethod。

五、存在问题分析以及解决方法

以上我们在服务提供者以及服务消费方都实现了服务降级处理,但是我们发现存在两个问题:

  • 1. 每个业务方法对应一个降级方法,配置起来很麻烦并且代码膨胀;
  • 2. 降级方法和业务方法的耦合性太强;

针对以上两个问题,我们可以通过下面的方法去改善。

  • 1. 针对代码膨胀、配置麻烦的问题,我们可以采用全局降级配置方法改善;
  • 2.针对耦合性太强,由于一般降级是在服务消费方进行,并且服务消费方通过Feign远程调用,所以我们针对Feign接口对每个方法做一个降级处理,将原先的降级处理代码和业务处理代码分开,这样就可以实现两者的解耦;

(一)、全局降级配置

修改【springcloud-provider-hystrix-payment8001】服务提供方,在业务层接口上添加:

  • @DefaultProperties(defaultFallback = "对应的统一降级方法")
@Service
@DefaultProperties(defaultFallback = "commonDefaultFallback")
public class PaymentService {
    /**
     * 全局降级方法统一配置
     */
    public String commonDefaultFallback() {
        return "[全局降级配置], sorry, the system is busy, please try again later!";
    }

    @HystrixCommand
    public String paymentInfoFail(Integer id) {
        //超时或者运行时异常都会引起服务降级
            
        //手动触发一个运行时异常,也会触发服务降级方法

        //注意:不要手动去try-catch这个异常,否则异常被捕获了,就不会走降级方法.
        String string = null;
        System.out.println(string.length());
        return "线程名称:  " + Thread.currentThread().getName() + ">>>>id:  " + id;
    }

}

这样配置之后,对于@HystrixCommand注解中没有特别指明降级方法fallbackMethod的统一都会执行降级方法,但是注意首先得加上@HystrixCommand注解开启服务降级。

重启项目,我们浏览器访问:http://localhost:8001/payment/hystrix/fail/100

可见,我们没有特别指明降级方法时,会到统一降级方法里面去执行,统一的降级和独自享有的降级方法各自分开,避免了代码膨胀,合理减少了代码量。

(二)、Feign远程调用降级配置

在前面的服务消费方【springcloud-consumer-feign-hystrix-order80】中,我们都知道FeignClient是一个接口:

public interface PaymentHystrixFeignClient {

里面声明了一些方法,那么我们可以思考一下,能否去实现这个接口,然后在实现类里面去自定义每个业务方法的降级处理逻辑呢,答案是肯定的,@FeignClient注解提供了一个属性fallback可用于指定服务降级的实现类。

下面我们定义Feign接口的服务降级类:

package com.wsh.springcloud.feign.fallback;

import com.wsh.springcloud.feign.PaymentHystrixFeignClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @Description 远程服务调用接口-失败回调类
 * @Date 2020/8/16 16:07
 * @Author weishihuai
 * 说明:
 */
@Component
public class PaymentFallbackFeignClientFallback implements PaymentHystrixFeignClient {
    private static final Logger logger = LoggerFactory.getLogger(PaymentFallbackFeignClientFallback.class);

    @Override
    public String paymentInfoSuccess(Integer id) {
        logger.error("远程服务调用【paymentInfoSuccess】失败!");
        return "sorry,[paymentInfoSuccess], the payment service is not available! \";";
    }

    @Override
    public String paymentInfoFail(Integer id) {
        logger.error("远程服务调用【paymentInfoFail】失败!");
        return "sorry,[paymentInfoFail], the payment service is not available! \";";
    }
}

然后在Feign接口中指定降级回调类: 

 重启【springcloud-consumer-feign-hystrix-order80】,此时我们模拟服务提供方发生宕机,停掉服务提供方【springcloud-provider-hystrix-payment8001】,浏览器访问:http://localhost/consumer/payment/hystrix/success/100

运行结果如下图:

可见,实现了Feign远程服务调用的降级处理。

六、服务熔断

关于服务熔断,著名的马丁富勒关于Hystrix写过一篇论文:https://martinfowler.com/bliki/CircuitBreaker.html

熔断器有三种状态:

  • 熔断关闭 Closed
  • 熔断开启 Open
  • 熔断半开 Half Open

熔断机制是应对雪崩效应的一种微服务链路保护机制。当扇出链路的某个微服务出错不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应结果。当检测到该节点微服务调用响应正常后,恢复调用链路。

在SpringCloud中,熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败,就会启动熔断机制,熔断机制的注解是@HystrixCommand

下面,我们改造服务提供方代码【springcloud-provider-hystrix-payment8001】:

【a】业务层接口添加如下方法:

/**
     * 测试服务熔断
     * 这里配置的几个参数表示: 10秒内请求10次数,如果超过60%的请求都是失败的,那么断路器将会开启.
     */
    @HystrixCommand(fallbackMethod = "testCircuitBreakerFallback", commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),// 是否开启断路器
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),// 请求次数
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), // 时间窗口期
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"),// 失败率达到多少后跳闸
    })
    public String testCircuitBreaker(@PathVariable("id") Integer id) {
        if (id < 0) {
            //抛出运行时异常,会调用服务降级方法testCircuitBreakerFallback
            throw new RuntimeException("id不能为负数");
        }
        return "ID: " + UUID.randomUUID().toString();
    }

    public String testCircuitBreakerFallback(@PathVariable("id") Integer id) {
        return "testCircuitBreaker【服务降级处理】,ID: " + id;
    }

【b】控制层添加如下方法

 //服务熔断
    @GetMapping("/payment/testCircuitBreaker/{id}")
    public String testCircuitBreaker(@PathVariable("id") Integer id) {
        return paymentService.testCircuitBreaker(id);
    }

启动项目后,

浏览器访问一次:http://localhost:8001/payment/testCircuitBreaker/-100

浏览器访问一次:http://localhost:8001/payment/testCircuitBreaker/100

可以看到,当ID为负数的时候,执行服务降级方法。

下面我们疯狂重试错误的请求【ID不满足条件,触发服务降级】:http://localhost:8001/payment/testCircuitBreaker/-100

注意,需要满足在10秒内发送10次请求,并且至少有60%的请求都是失败的,这一步主要是触发断路器由CLOSED关闭状态到OPEN打开状态。

在断路器变为开启状态下,我们访问一次正确的路径:http://localhost:8001/payment/testCircuitBreaker/100

发现,当断路器开启之后,原本正确的访问都变得直接走降级方法了。

注意:多次错误之后,然后慢慢正确,发现刚开始不满足条件,就算是正确的访问地址也不能正常返回数据。在慢慢恢复正常后,发现断路器又变为关闭状态了,正确的请求也能正确返回数据。

断路器小总结:

在微服务中使用Hystrix 作为断路器时,通常涉及到一下三个重要的指标参数(这里是写在@HystrixProperties注解中,当然实际项目中可以全局配置在yml或properties中)。

1、circuitBreaker.sleepWindowInMilliseconds

断路器的快照时间窗,也叫做时间窗口期。可以理解为一个触发断路器的周期时间值,默认为10秒(10000)

2、circuitBreaker.requestVolumeThreshold

断路器的窗口期内触发断路的请求阈值,默认为20。换句话说,假如某个窗口期内的请求总数都不到该配置值,那么断路器连发生的资格都没有。断路器在该窗口期内将不会被打开。

3、circuitBreaker.errorThresholdPercentage

断路器的窗口期内能够容忍的错误百分比阈值,默认为50(也就是说默认容忍50%的错误率)。打个比方,假如一个窗口期内,发生了100次服务请求,其中50次出现了错误。在这样的情况下,断路器将会被打开。在该窗口期结束之前,即使第51次请求没有发生异常,也将被执行fallback逻辑。

综上所述,在以上三个参数缺省的情况下,Hystrix断路器触发的默认策略为:

在10秒内,发生20次以上的请求时,假如错误率达到50%以上,则断路器将被打开。(当一个窗口期过去的时候,断路器将变成半开(HALF-OPEN)状态,如果这时候发生的请求正常,则关闭,否则又打开)

七、Hystrix Dashboard仪表盘监控

除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等。Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。SpringCloud也提供了Hystrix Dashboard的整合,对监控内容转化为可视化界面。

下面,我们通过一个示例说明Hystrix Dashboard的使用。

新建一个module【springcloud-consumer-hystrix-dashboard9001】

【a】pom.xml中加入spring-cloud-starter-netflix-hystrix-dashboard依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud2020</artifactId>
        <groupId>com.wsh.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-consumer-hystrix-dashboard9001</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

【b】application.yml

server:
  port: 9001

【c】主启动类添加@EnableHystrixDashboard注解

package com.wsh.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@SpringBootApplication
//开启仪表盘监控功能
@EnableHystrixDashboard
public class HystrixDashboardServiceApplication9001 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixDashboardServiceApplication9001.class, args);
    }
}

【d】启动项目

浏览器访问:http://localhost:9001/hystrix

可见,微服务监控平台已经搭建成功。下面我们以监控服务提供者【springcloud-provider-hystrix-payment8001】为例,讲解如何看懂Hystrix Dashboard仪表盘的统计信息。需要修改一下几处础地方:

【a】确保【springcloud-provider-hystrix-payment8001】加入actuator监控依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

【b】HystrixPaymentServiceApplication8001启动类添加如下配置:

新版本Hystrix需要在主启动类中指定监控路径,否则可能会报:Unable to connect to Command Metric Stream.


@SpringBootApplication
@EnableEurekaClient
//@EnableCircuitBreaker开启Hystrix断路器功能
@EnableCircuitBreaker
public class HystrixPaymentServiceApplication8001 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixPaymentServiceApplication8001.class, args);
    }

    /**
     * 此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑
     * ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",
     * 只要在自己的项目里配置上下面的servlet就可以了
     */
    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }

}

【c】下面我们使用Hystrix Dashboard监控【springcloud-provider-hystrix-payment8001】微服务

浏览器随机访问:http://localhost:8001/payment/testCircuitBreaker/100http://localhost:8001/payment/testCircuitBreaker/-100,观察仪表盘监控统计信息如下图所示: 

 

监控界面实时展示了两分钟内接口请求的流量、请求成功百分比、成功数、失败数、超时数等等。更多关于仪表盘的使用可以参考SpringCloud旧版本笔者总结的一篇文章:https://blog.csdn.net/Weixiaohuai/article/details/82699125 进行学习。

八、总结

以上就是Hystrix断路器的使用,服务降级处理方法,服务熔断进行详细的说明,相关项目的代码我已经放在Gitee上,有需要的小伙伴可以去拉取进行学习:https://gitee.com/weixiaohuai/springcloud_Hoxton,由于笔者水平有限,如有不对之处,还请小伙伴们指正,相互学习,一起进步。

展开阅读全文
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值