7_Hystrix中的服务降级和熔断

👉写在前面 : 前面我们使用了 OpenFeign 进行服务的调用,假如现在服务提供者出现了请求超时,宕机或者异常等情况,是直接让整个微服务死掉还是该怎么办 ?或者说这些都不会发生,但是此时服务提供的资源已经都被占用了,是让其直接死掉呢 ?还是先缓一缓 ?

  • 什么情况下会发生服务降级 ?
    • 服务降级具体是怎么做的 ?
    • 一个请求对应一个兜底方法有什么问题 ?
    • 使用全局 fallback 方法会存在什么问题 ?
    • 配合 OpenFeign 进行服务降级有什么好处 ?
  • 什么情况下会发生服务熔断 ?
    • 服务熔断和服务降级有什么关系 ?
    • 服务熔断和服务降级最大区别是什么 ?
    • 服务熔断使用的几个字段参数具体是什么含义 ?
    • 什么条件下会发生服务熔断 ?
    • 发生服务熔断后,它的工作流程是怎样的 ?
  • 什么情况下会发生服务限流 ?
  • Hystrix 的工作流程是怎样的 ?
  • 如果想要查看具体的 http 请求失败还是成功,该怎么办 ?
    • HystrixDashboard 具体怎么使用 ?
    • 各种参数该怎么看 (七种颜色代表什么、圆圈代表什么、折线呢)?
    • 怎样通过 HystrixDashboard 查看熔断器状态 ?

7_Hystrix中的服务降级和熔断

Hystrix断路器

Hystrix官宣停更,官方推荐使用:resilence4j 替换,同时国内 Spring Cloud Alibaba 提出了 Sentinel 实现熔断和限流 。

resilence4j 国外用的比较多,国内一般使用Sentinel

概述

分布式面临的问题

复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败(网络卡顿,网络超时)

在这里插入图片描述

服务雪崩

多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的 雪崩效应 。

对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其它系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统 。

通常当你发现一个模块下的某个实例失败后,这时候这个模块依然还会接收流量,然后这个有问题的模块还调用了其他的模块,这样就会发生级联故障,或者叫雪崩 。

HyStrix的诞生

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

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

Hystrix作用

  • 服务降级
  • 服务熔断
  • 接近实时的监控(Hystrix Dashboard)
  • 。。。。

Hystrix重要概念

服务降级

fallback:假设对方服务不可用了,那么至少需要返回一个兜底的解决方法,即向服务调用方返回一个符合预期的,可处理的备选响应 。

例如:服务繁忙,请稍后再试,不让客户端等待并立刻返回一个友好的提示,fallback

哪些情况会触发降级

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

服务熔断

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

一般过程:服务降级 -> 服务熔断 -> 恢复调用链路【与服务降级的最大区别】

服务限流

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

Hystrix案例

服务提供者

1、建 Module:cloud-provider-hystrix-payment8001
2、改 POM

引入:

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

完整版:

<?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>spring_cloud_yang</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-hystrix-payment8001</artifactId>
    <dependencies>
        <dependency>
            <!-- 引用自己定义的api通用包,可以使用Payment支付Entity -->
            <groupId>org.example</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </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>
        <!-- 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>
        <!--热部署-->
        <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>
3、建 YML
# 端口号
server:
  port: 8001
spring:
  application:
    name: cloud-provider-hystrix-payment

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
       defaultZone: http://eureka7001.com:7001/eureka/
4、主启动类
/**
 * @Author: xj0927
 * @Description:
 * @Date Created in 2020-10-30 8:55
 */
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker  //激活hystrix组件
public class PaymentHystrixMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentHystrixMain8001.class, args);
    }
}
5、业务类

service 层

@Service
public class PaymentService {

    public String payment_ok(Integer id){
        return Thread.currentThread().getName() + "payment_ok,id:" + id;
    }
}

controller 层

@RestController
@Slf4j
public class PaymentController {
    @Autowired
    private PaymentService paymentService;

    //运行正常情况
    @GetMapping("/payment/hystrix/ok/{id}")
    public String payment_ok(@PathVariable Integer id){
        String result = paymentService.payment_ok(id);
        log.info("****" + result);
        return result;
    }
    //超时情况
    @GetMapping("/payment/hystrix/outTime/{id}")
    public String payment_outTime(@PathVariable Integer id){
        String result = paymentService.payment_outTime(id);
        log.info("****" + result);
        return result;
    }

}

高并发测试

Jmeter高并发测试:我们创建 20000个线程去访问

在这里插入图片描述

访问刚刚我们写的两个 延时接口
在这里插入图片描述

我们会发现当线程多的时候,会直接卡死,甚至把其它正常的接口都已经拖累

这是因为我们使用 20000个线程去访问那个延时的接口,这样会把该微服务的资源全部集中处理 延时接口,而导致正常的接口资源不够,出现卡顿的现象。

同时 tomcat 的默认工作线程数被打满,没有多余的线程来分解压力和处理。

服务消费者加入

刚刚我们能够看到,光是调用服务提供者就不能支持 20000的 并发量,这个时候,在使用服务消费者的引入,同时请求该接口,这个时候我们就需要在服务消费端设置服务降级了 。

1、建 Module :cloud-consumer-feign-hystrix-order80
2、改 POM
<?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>spring_cloud_yang</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-feign-hystrix-order80</artifactId>
    <dependencies>
        <dependency><!-- 引用自己定义的api通用包,可以使用Payment支付Entity -->
            <groupId>org.example</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--监控-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <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>
        <!--热部署-->
        <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>
3、建 YML
# 端口
server:
  port: 80

spring:
  application:
    name: cloud-consumer-hystrix-order
eureka:
  client:
    register-with-eureka: false
    service-url:
       defaultZone: http://eureka7001.com:7001/eureka/

4、主启动类

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients  //激活feign
@EnableHystrix  //启用hystrix
public class OrderHystrixMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderHystrixMain80.class,args);
    }
}
4、业务类

最后我们在 feign 调用上增加 fallBack

@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT")
public interface OrderHystrixService {
    //正常访问
    @GetMapping("/payment/hystrix/ok/{id}")
    public String payment_ok(@PathVariable(value = "id") Integer id);
	
    //超时访问
    @GetMapping("/payment/hystrix/outTime/{id}")
    public String payment_outTime(@PathVariable(value = "id") Integer id);
}

也同样将 20000 个线程打到服务上,会发现更慢。

解决方案

原因:超时导致服务器变慢,超时不再等待,服务出错,宕机或者程序运行出错,出错要有兜底 。

解决:

  • 对方服务8001超时了,调用者80不能一直卡死等待,必须有服务降级
  • 对方服务8001宕机了,调用者80不能一直卡死,必须有服务降级
  • 对方服务8001正常,调用者自己出故障或者有自我要求(自己的等待时间小于服务提供者),自己处理降级
服务降级

需要使用新的注解 @HystrixCommand,同时需要在主启动类上新增:@EnableCircuiteBreaker

模拟请求服务超时

设置 8001 自身调用超时时间的峰值【 3s 】,峰值内可以正常运行,超过了需要有兜底的方法处理,作为服务降级 fallback 。

   /**
     * 超时访问
     *
     * @param id
     * @return
     */
    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
    })
    public String paymentInfo_TimeOut(Integer id) {
        int timeNumber = 5;
        try { TimeUnit.SECONDS.sleep(timeNumber); } catch (InterruptedException e) { e.printStackTrace();}
        return "线程池:" + Thread.currentThread().getName() + " paymentInfo_TimeOut,id:" + id + "\t" +
                "O(∩_∩)O哈哈~  耗时(秒)";
    }

    /**
     * 兜底的解决方案
     * @param id
     * @return
     */
    public String paymentInfo_TimeOutHandler(Integer id){
        return "线程池:" + Thread.currentThread().getName() + " 8001系统繁忙请稍后再试!!,id:" + id + "\t"+"我哭了!!";
    }

上述的方法就是当在规定的 3 秒内没有完成,那么就会触发服务降级,返回一个兜底的解决方案同时不仅是超时,

模拟服务请求异常

假设服务内的方法出现了异常,也同样会触发兜底的解决方法,例如下面的代码,我们制造出一个除数为0的异常。

    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
    })
    public String paymentInfo_TimeOut(Integer id) {
        int timeNumber = 10 / 0;
        return "线程池:" + Thread.currentThread().getName() + " paymentInfo_TimeOut,id:" + id + "\t" +
                "O(∩_∩)O哈哈~  耗时(秒)";
    }

上述说的是服务提供方的降级,服务消费者也需要设置服务降级的处理保护,也就是对客户端进行保护

服务消费方降级

也就是说服务降级,既可以放在客户端,也可以放在服务端,一般而言是放在客户端进行服务降级的

1、主启动类

首先主启动类设置:@EnableHystrix

配置过的 devtool 热部署对 java 代码的改动明显,但是对@HystrixCommand内属性的修改建议重启微服务

2、改 YML

引入:

feign:
  hystrix:
  # 开启 hystrix
    enabled: true

完整版:

# 端口
server:
  port: 80

spring:
  application:
    name: cloud-consumer-hystrix-order
eureka:
  client:
    register-with-eureka: false
    service-url:
       defaultZone: http://eureka7001.com:7001/eureka/
# 开启 hystrix 用于服务降级,在注解@FeignClient中添加fallbackFactory属性
feign:
  hystrix:
    enabled: true
3、业务逻辑类

服务消费端降级

    @GetMapping("/consumer/payment/hystrix/outTime/{id}")
    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500")
    })
    public String payment_outTime(@PathVariable Integer id){
        int time = 10/0;//模拟异常情况
        return service.payment_outTime(id);
    }
    //对应处理措施
    public String paymentInfo_TimeOutHandler(Integer id){
        return "我是消费方80,出现超时等待或异常了";
    }
目前问题

目前异常处理的方法,和业务代码耦合,这就造成耦合度比较高 【一个请求就要对应一个fallback进行兜底,如果很多咋办 ?】。

解决措施

解决方法就是使用统一的服务降级方法 。

方法1:设置全局 fallback

除了个别重要核心业务有专属,其它普通的可以通过@DefaultProperties(defaultFallback = ""),这样通用的和独享的各自分开,避免了代码膨胀,合理减少了代码量。

可以在Controller处设置: @DefaultProperties(defaultFallback = “payment_Global_FallbackMethod”)

/**
 * @Author: xj0927
 * @Description:
 * @Date Created in 2020-10-30 9:46
 */
@RestController
@Slf4j
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")//定义全局fallback
public class OrderHystrixController {
    @Autowired
    private OrderHystrixService service;

    @GetMapping("/consumer/payment/hystrix/outTime/{id}")
    @HystrixCommand  //不指定具体的哪一个处理方法
    public String payment_outTime(@PathVariable Integer id){
        int time = 10/0;//模拟异常情况
        return service.payment_outTime(id);
    }

    //下面是全局fallback
    public String payment_Global_FallbackMethod(){
        return "Global异常处理信息,请稍后再试~~";
    }
}
方法2:配合 feign进行处理

我们现在还发现,兜底的方法 和 我们的业务代码 耦合在一块比较混乱 。

我们可以在 feign 调用的时候,增加 hystrix 的服务降级处理的实现类,这样就可以进行解耦。

格式:@FeignClient(fallback = PaymentFallbackService.class)

我们要面对的异常主要有

  • 发生异常
  • 请求超时
  • 服务提供者宕机

需要新建一个 FallbackService 实现类,然后通过实现类统一为 feign 接口里面的方法进行异常处理

feign 接口【代替 Ribbon + RestTemplate】:

@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = OrderHystrixFallbackService.class)
public interface OrderHystrixService {
    @GetMapping("/payment/hystrix/ok/{id}")
    public String payment_ok(@PathVariable(value = "id") Integer id);

    @GetMapping("/payment/hystrix/outTime/{id}")
    public String payment_outTime(@PathVariable(value = "id") Integer id);
}

实现类:

@Component
public class OrderHystrixFallbackService implements OrderHystrixService {
    @Override
    public String payment_ok(Integer id) {
        return "-----payment_ok-------";
    }

    @Override
    public String payment_outTime(Integer id) {
        return "-----payment_outTime------";
    }
}

通过这种方式,这个时候,如果我们将服务提供方进行关闭,但是我们在客户端做了服务降级处理,让客户端在服务端不可用时,也会获得提示信息,而不会挂起耗死服务器 。

服务熔断

发生服务熔断后,会先进行服务降级 。

熔断概念

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

当检测到该节点微服务调用响应正常后,恢复调用链路

在 Spring Cloud 框架里,熔断机制通过 Hystrix 实现,Hystrix 会监控微服务间调用的状况,当失败的调用到一定的阈值,缺省是5秒内20次调用失败,就会启动熔断机制,熔断机制的注解还是 @HystrixCommand
在这里插入图片描述

熔断器的三种状态:打开,关闭,半开

这里提出了 半开的概念,首先打开一半的,然后慢慢的进行恢复,最后在把断路器关闭

降级 -> 熔断 -> 恢复

案例

字段解释:

// 是否开启断路器
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),

// 请求次数
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),

// 时间窗口期/时间范文
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),

// 失败率达到多少后跳闸
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")

在服务提供方 8001,增加服务熔断:

@Service
public class PaymentService {

    /** 服务熔断 */
    @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",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 paymentCircuitBreaker(Integer id){
        if(id < 0){
            throw new RuntimeException("id不能为负数****");
        }
        String serialNumber = IdUtil.simpleUUID();
        return Thread.currentThread().getName() + "调用成功,流水号" + serialNumber;
    }
    //先进行相应的服务降级的方法
    public String paymentCircuitBreaker_fallback(Integer id){
        return "id 不能为负数,请稍后再试~~ " + id;
    }
}

首先是是否开启熔断器,然后是在一个时间窗口内,有 60% 的失败,那么就启动断路器,也就是10次里面,6次失败,【在时间窗口期内,既要满足请求的次数,也要满足失败率 !!!】

当断路器被打开的时候,即使是正确的请求,该方法也会被断路。

总结
熔断类型
  • 熔断打开:请求不再进行调用当前服务,内部设置时钟一般为MTTR(平均故障处理时间),当打开时长达所设时钟则进入半熔断状态
  • 熔断关闭:熔断关闭不会对服务进行熔断
  • 熔断半开:部分请求根据规则调用当前服务,如果请求成功且符合规则,则认为当前服务恢复正常,关闭熔断
断路器启动条件

在这里插入图片描述

涉及到断路器的三个重要参数:快照时间窗,请求总阈值,错误百分比阈值

  • 快照时间窗:断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒。
  • 请求总数阈值:在快照时间窗口内,必须满足请求总数阈值才有资格熔断。默认为20,意味着在10秒内,如果hystrix的调用总次数不足20次,即使所有请求都超时或者其他原因失败,断路器都不会打开。
  • 错误百分比阈值:当请求总数在快照时间窗内超过了阈值,比如发生了30次调用,并且有15次发生了超时异常,也就是超过了50的错误百分比,在默认设定的50%阈值情况下,这时候就会将断路器打开
开启和关闭的条件
  1. 当满足一定阈值的时候(默认10秒内超过20个请求)
  2. 当失败率达到一定的时候(默认10秒内超过50%的请求失败)
  3. 到达以上阈值,断路器将会开启
  4. 当开启的时候,所有请求都不会进行转发
  5. 一段时间之后(默认是5秒),这个时候断路器是半开状态,会让其中一个请求进行转发。如果成功,断路器会关闭,若失败,继续开启,重复4和5
断路器开启后
  • 再有请求调用的时候,将不会调用主逻辑,而是直接调用降级 fallback,通过断路器,实现了自动的发现错误并将降级逻辑切换为主逻辑,减少相应延迟的效果。
  • 原来的主逻辑如何恢复?
    • 对于这个问题,Hystrix 实现了自动恢复功能,当断路器打开,对主逻辑进行熔断之后,hystrix 会启动一个休眠时间窗,在这个时间窗内,降级逻辑是临时的成为主逻辑,当休眠时间窗到期,断路器将进入半开状态,释放一次请求到原来的主逻辑上,如果此次请求正常返回,断路器将继续闭合,主逻辑恢复,如果这次请求依然有问题,断路器继续保持打开状态,休眠时间窗重新计时。
服务限流

这部分后面讲解阿里巴巴的 Sentinel 的时候进行说明

Hystrix工作流程

在这里插入图片描述

蓝色:调用路径

红色:返回路径

完整的请求路线:

  1. 选择一个Hystrix注册方式
  2. 二选一即可
  3. 判断缓存中是否包含需要返回的内容(如果有直接返回)
  4. 断路器是否为打开状态(如果是,直接跳转到8,返回)
  5. 断路器为健康状态,判断是否有可用资源(没有,直接跳转8)
  6. 构造方法和Run方法
  7. 将正常,超时,异常的消息发送给断路器
  8. 调用getFallback方法,也就是服务降级
  9. 直接返回正确结果

服务监控HystrixDashboard

概述

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

1、建 Module:cloud-consumer-hystrix-dashboard9001

2、改 POM

引入:

<!--hystrix dashboard-->
<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>

完整版:

<?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>spring_cloud_yang</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-hystrix-dashboard9001</artifactId>
    <dependencies>
        <dependency><!-- 引用自己定义的api通用包,可以使用Payment支付Entity -->
            <groupId>org.example</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <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.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>
        <!--热部署-->
        <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>

3、建 YML

# 端口号
server:
  port: 9001

4、主启动类

使用 @EnableHystrixDashboard 注解开启图形化的 hystrix

/**
 * @Author: xj0927
 * @Description:
 * @Date Created in 2020-10-30 12:14
 */
@SpringBootApplication
@EnableHystrixDashboard //开启图形化的hystrix
public class HystrixDashboardMain9001 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixDashboardMain9001.class,args);
    }
}

同时,最后我们需要注意,每个服务类想要被监控的,都需要在 pom 文件中,添加一下注解:

最好是每次和 web 依赖一起引入!!

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

同时在服务提供者的启动类上,需要添加以下的内容:

引入即可,具体不用太关注!!!

@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class PaymentHystrixMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentHystrixMain8001.class, args);
    }
    
    /**
    * @Description: 此配置是为了服务监控而配置,与服务容错本身无关,spring cloud升级后的坑
    * @Return: org.springframework.boot.web.servlet.ServletRegistrationBean
    * @Author: xj0927
    * @Date Created in 2020/10/30 12:21
    */
    @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;
    }
}

5、测试

输入以下地址,进入Hystrix的图形化界面

http://localhost:9001/hystrix

在这里插入图片描述

6、使用监控

我们需要使用当前 hystrix 需要监控的端口号,也就是使用 9001 去监控 8001,即使用hystrix dashboard去监控服务提供者的端口号

在这里插入图片描述

然后我们运行

http://localhost:8001/Hystrix/circuitBreaker/31

就能够发现 Hystrix Dashboard 能够检测到我们的请求

在这里插入图片描述

假设我们访问错误的方法后

http://localhost:8001/Hystrix/circuitBreaker/-31

我们能够发现,此时断路器处于开启状态,并且错误率百分100

在这里插入图片描述

如何读其中的内容 ?

首先是七种颜色,

每个颜色都对应的一种结果:

在这里插入图片描述

在这里插入图片描述

然后是里面的圆:

实心圆:共有两种含义。它通过颜色的变化代表了实例的健康程度,它的健康程度从

绿色 < 黄色 < 橙色 <红色,递减该实心圆除了颜色变化之外,它的大小也会根据实例的请求流量发生变化,流量越大该实心圆就越大,所以通过该实心圆的展示,就可以快速在大量的实例中快速发现故障实例和高压力实例 。

最后是曲线:

用于记录 2 分钟内流量的相对变化,可以通过它来观察到流量的上升和下降趋势 。

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值