服务熔断-Hystrix

为什么需要断路器

在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用(RPC)。为了保证其高可用,单个服务又必须集群部署。由于网络原因或者自身的原因,服务并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会出现网络延迟,此时若有大量的网络涌入,会形成任务累计,导致服务瘫痪,甚至导致服务“雪崩”。为了解决这个问题,就出现断路器模型。

简单理解:当微服务A 调用微服务B 微服务B调用微服务C微服务C调用微服务D。当调用的链路非常多时。假设微服务D因为其他原因不可用。微服务A在占用资源等待返回,如果流量访问过大,瞬间将微服务A的资源用完,服务器可能崩溃。导致很多问题。形成雪崩效应

Hystrix概述

Hystrix是用于处理分布式系统的延迟和容错的开源库,在分布式系统中,某一个服务的超时、异常是必不可免的。Hystrix能保证就算服务错误的情况下,也返回一些提示,从而解决一些整体服务失败,避免级联故障,提高分布式系统的弹性

测试环境搭建

1、创建主工程,空的maven项目

2、导入依赖,并删除src目录

<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wyx</groupId>
    <artifactId>Hystrix</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEmcoding>UTF-8</project.build.sourceEmcoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <!--对应的版本-->
        <spring.boot.dependencies.version>2.4.3</spring.boot.dependencies.version>
        <spring.cloud.dependencies.version>2020.0.2</spring.cloud.dependencies.version>
        <spring.cloud.alibaba.dependencies.version>2.2.1.RELEASE</spring.cloud.alibaba.dependencies.version>
        <mysql.version>8.0.23</mysql.version>
        <druid.version>1.2.5</druid.version>
        <druid.spring.boot.version>1.2.5</druid.spring.boot.version>
        <log4j.version>1.2.17</log4j.version>
        <junit.version>4.13</junit.version>
        <lombok.version>1.18.20</lombok.version>
        <mybatis.spring.boot.version>2.1.4</mybatis.spring.boot.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!--SpringBoot 依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.dependencies.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--Spring Cloud 依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.dependencies.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--Spring Cloud Alibaba 依赖-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring.cloud.alibaba.dependencies.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--Mysql 连接驱动-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>

            <!--druid 依赖-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>

            <!--Spring Boot 启动器-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>${druid.spring.boot.version}</version>
            </dependency>

            <!--Lombok 依赖-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>

            <!--log4j 依赖-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>

            <!--junit 单元测试 依赖-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>

            <!--Mybatis-spring-boot 启动器-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.spring.boot.version}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.4.4</version>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

微服务提供者

1、在主工程下提交空的maven项目 cloud-provider-hystrix8001,并导入依赖

这里使用consul做注册中心:不会使用consul参考这里:Consul注册中心的使用

<dependencies>
    <!--连接 consul 的依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-consul-discovery</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <version>2.2.8.RELEASE</version>
    </dependency>

    <!--spring-boot-web 模块 常用的3个-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</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>
    <!--热部署插件-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <!--测试插件-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-test</artifactId>
        <scope>test</scope>
    </dependency>
    <!--lombok 依赖-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

2、创建application.yml

server:
  port: 8001

spring:
  application:
    name: cloud-provider-hystrix

  cloud:
    consul:
      # 服务的主机
      host: localhost
      # 服务的端口号
      port: 8500
      discovery:
        # 注册到服务中心的名称
        service-name: ${spring.application.name}

3、主启动类

package com.wyx.cloud;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ProviderHystrixMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(ProviderHystrixMain8001.class,args);
    }
}

4、业务逻辑

package com.wyx.cloud.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;

@Service
public class Provider {

    public String getInfo(){
        return "获取服务成功!😀😀😀😀";
    }


    @HystrixCommand(fallbackMethod = "getInfoOutTimeHandler",commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
    })
    public String getInfoOutTime(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "Error:获取服务失败!!!😂😂😂😂";
    }

}

package com.wyx.cloud.controller;

import com.wyx.cloud.service.Provider;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class ProviderController {

    @Resource
    Provider provider;


    @GetMapping("/getInfo")
    public String getInfo(){
        return provider.getInfo();
    }

    @GetMapping("/getInfoOutTime")
    public String getInfoOutTime(){
        return provider.getInfoOutTime();
    }

}

微服务消费者

1、创建空的maven工程 cloud-consumer-hystrix80 并导入依赖

    <dependencies>

        <!--连接 consul 的依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.8.RELEASE</version>
        </dependency>

        <!--spring-boot-web 模块 常用的3个-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</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>
        <!--热部署插件-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!--测试插件-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--lombok 依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

2、添加application.yml文件

server:
  port: 80

spring:
  application:
    name: cloud-consumer-hystrix

  cloud:
    consul:
      # 服务的主机
      host: localhost
      # 服务的端口号
      port: 8500
      discovery:
        # 注册到服务中心的名称
        service-name: ${spring.application.name}

3、创建主启动类

package com.wyx.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ConsumerHystrixMain80 {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerHystrixMain80.class,args);
    }

}

4、创建openfeign的调用接口

package com.wyx.cloud.service;

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

@Service  // 注入容器
@FeignClient("cloud-provider-hystrix") // 需要提供服务的服务注册名,也是服务提供者的spring.application.name
public interface Provider {

    @GetMapping("/getInfo")
    public String getInfo();

    @GetMapping("/getInfoOutTime")
    public String getInfoOutTime();

}

5、创建控制业务接口

package com.wyx.cloud.controller;

import com.wyx.cloud.service.Provider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
@Slf4j
public class ConsumerController {

    @Resource
    Provider provider;

    @GetMapping("/getInfo")
    public String getInfo(){
        return provider.getInfo();
    }

    @GetMapping("/getInfoOutTime")
    public String getInfoOutTime(){
        return provider.getInfoOutTime();
    }
}

使用jmeter 来做高并发测试:具体测试方法参考网上。

开启测试后、在访问时速度明显减慢。如果访问量继续增加,在真实环境下,服务器可能会宕机导致服务不可用,于是我们开始使用Hystrix来解决以上出现的问题。

主要功能

服务降级

当提高服务的应用出现问题后,返回一些友好提示来保证其他服务的调用不会出错。Fallback

触发原因:程序运行异常返回超时服务熔断触发线程池资源不足

使用服务降级

在服务提供方使用服务降级:

1、导入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <version>2.2.8.RELEASE</version>
</dependency>

2、添加错误后调用的方法fallback

// 一般放在使用 @HystrixCommand 的类中
public String getInfoOutTimeHandler(){
    return "访问超时!!!!";
}

3、添加注解

/*
* @HystrixCommand 作用与方法上,
* fallbackMethod 出错后调用的方法
* commandProperties 配置超时的时间
* */
@HystrixCommand(fallbackMethod = "getInfoOutTimeHandler",commandProperties = {
    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
})

4、主启动类添加自动开启注解

// 老版本可以使用 @EnableCircuitBreaker,新版本中该注解已经过时
@EnableHystrix

测试即可

修改微服务提供方的getInfoOutTime方法,在线程睡眠前面添加错误代码

int x = 10/0;

再次测试:发现这次就算不超时,也会走我们编写的getInfoOutTimeHandler方法

总结:在@HystrixCommand注解中,如果放回时间超时,或者程序运行时出现异常,等情况都会走我们编写的服务getInfoOutTimeHandler方法

在服务消费端使用服务降级:

1、导入依赖

<!--老版本中自带了openfeign 自带了 hystrix 可以不用导入,新版本必须引入依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <version>2.2.8.RELEASE</version>
</dependency>

注意:老版本虽然不用导入依赖,但是必须要在application.yml中添加开启hystrix功能

feign:
  hystrix:
    enable:  true

2、在主启动类上添加开启hystrix功能

@EnableHystrix

3、编写错误处理方法

public String getInfoOutTimeHandler(){
    return "消费者80:运行出错或等待返回结果超时!!!🤢🤢🤢";
}

4、在要处理的方法上添加注解

// 这里调节 1秒,然而服务器需要3秒才响应
@HystrixCommand(fallbackMethod = "getInfoOutTimeHandler",commandProperties = {
    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")
})

在上面的使用过程中出现了以下问题

  1. 每个方法都需要一个服务失败后的解决方法。
  2. 业务逻辑代码和出错解决方法混在一块,系统耦合度高。

下面针对以上问题,我们做一定的修改。

全局错误返回配置方法

1、配置全局出错的方法

// 也是在类中
public String getGlobalFallbackMethod(){
    return "全局错误返回错误的方法!!";
}

2、在需要使用服务降级的类上添加服务降级的默认配置

// getGlobalFallbackMethod 为刚刚我们定义的方法
@DefaultProperties(defaultFallback = "getGlobalFallbackMethod")

3、在需要进行服务降级的方法上添加注解

@HystrixCommand

注意点:这里配置了全局的出错处理,如果@HystrixCommand详细配置了自己出错走的方法,就默认走自己的,没有就使用全局配置。

解耦业务逻辑代码的混乱问题

1、编写一个类实现openfeign调用的服务接口

package com.wyx.cloud.service;

import org.springframework.stereotype.Component;

// 重写方法,如果服务错误就会调用这里的方法
@Component
public class ProviderFallBack implements Provider{

    @Override
    public String getInfo() {
        String msg = "getInfo:解耦业务逻辑中出错的服务降级";
        return msg;
    }

    @Override
    public String getInfoOutTime() {
        String msg = "getInfoOutTime:解耦业务逻辑中出错的服务降级";
        return msg;
    }
}

2、修改接口的@FeignClient注解

// 原来的:@FeignClient(value = "cloud-provider-hystrix")
// 修改添加 fallback 填写自己实现接口的类。
@FeignClient(value = "cloud-provider-hystrix",fallback = ProviderFallBack.class) 

运行测试即可

服务熔断

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

原理图:

  • Closed:熔断器关闭状态(所有请求返回成功)
  • Open:熔断器打开状态(调用次数累计到达阈值或者比例,熔断器打开,服务直接返回错误)
  • Half Open:熔断器半开状态(默认时间过后,进入半熔断状态,允许定量服务请求,如果调用都成功,则认为恢复了,则关闭断路器,反之打开断路器)
/*
*  以下为服务熔断代码
* */
@HystrixCommand(commandProperties = {
    //设置服务熔断功能开启
    @HystrixProperty(name="circuitBreaker.enabled",value = "true"),
    //设置服务熔断请求次数,达到这个这个阈值才会触发熔断
    @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value = "10"),
    //设置服务熔断百分比;失败率超过这个百分比才能熔断。
    @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value = "50"),
    //设置服务熔断时间窗口期
    @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value = "10000")
})
@GetMapping("/ronduan/{id}")
public String ronDuan(@PathVariable int id){
    if(id<0){
        throw new RuntimeException("ID不可为负数!");
    }
    return "服务调用成功:"+id+":"+ UUID.randomUUID();
}

熔断器三个重要参数:快照时间窗、请求总数阈值、错误百分比阈值

快照时间窗:断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒;

请求总数阈值:在快照时间窗内,必须满足请求总数阈值才有资格熔断。默认为20,意味着在10秒内,如果该hystrix命令的调用次数不足20次,即使所有的请求都超时或者其他原因失败,断路器都不会打开。

错误百分比阈值:当请求总数在快照时间窗内超过了阈值,比如发生了30次调用,如果在这30次调用中,有15次发生了超时异常,也就是超过50%的错误百分比,在默认设定50%阈值情况下,这时候才会将熔断器打开。

全部配置:

//Command Properties
//Execution相关的属性的配置:
execution.isolation.strategy //隔离策略,默认是Thread, 可选Thread|Semaphore
execution.isolation.thread.timeoutInMilliseconds //命令执行超时时间,默认1000ms
execution.timeout.enabled //执行是否启用超时,默认启用true
execution.isolation.thread.interruptOnTimeout //发生超时是是否中断,默认true
execution.isolation.semaphore.maxConcurrentRequests //最大并发请求数,默认10,该参数当使用ExecutionIsolationStrategy.SEMAPHORE策略时才有效。如果达到最大并发请求数,请求会被拒绝。理论上选择semaphore size的原则和选择thread size一致,但选用semaphore时每次执行的单元要比较小且执行速度快(ms级别),否则的话应该用thread。semaphore应该占整个容器(tomcat)的线程池的一小部分。

//Fallback相关的属性
//这些参数可以应用于Hystrix的THREAD和SEMAPHORE策略

fallback.isolation.semaphore.maxConcurrentRequests //如果并发数达到该设置值,请求会被拒绝和抛出异常并且fallback不会被调用。默认10
fallback.enabled //当执行失败或者请求被拒绝,是否会尝试调用hystrixCommand.getFallback() 。默认true

//Circuit Breaker相关的属性

default.circuitBreaker.enabled //用来跟踪circuit的健康性,如果未达标则让request短路。默认true
circuitBreaker.requestVolumeThreshold 一个rolling window内最小的请求数。如果设为20,那么当一个rolling window的时间内(比如说1个rolling window是10秒)收到19个请求,即使19个请求都失败,也不会触发circuit break。默认20
circuitBreaker.sleepWindowInMilliseconds //触发短路的时间值,当该值设为5000时,则当触发circuit break后的5000毫秒内都会拒绝request,也就是5000毫秒后才会关闭circuit。默认5000
circuitBreaker.errorThresholdPercentage //错误比率阀值,如果错误率>=该值,circuit会被打开,并短路所有请求触发fallback。默认50
circuitBreaker.forceOpen //强制打开熔断器,如果打开这个开关,那么拒绝所有request,默认false
circuitBreaker.forceClosed  //强制关闭熔断器 如果这个开关打开,circuit将一直关闭且忽略circuitBreaker.errorThresholdPercentage
  
//Metrics相关参数
metrics.rollingStats.timeInMilliseconds //设置统计的时间窗口值的,毫秒值,circuit break 的打开会根据1个rolling window的统计来计算。若rolling window被设为10000毫秒,则rolling window会被分成n个buckets,每个bucket包含success,failure,timeout,rejection的次数的统计信息。默认10000
metrics.rollingStats.numBuckets //设置一个rolling window被划分的数量,若numBuckets=10,rolling window=10000,那么一个bucket的时间即1秒。必须符合rolling window % numberBuckets == 0。默认10
metrics.rollingPercentile.enabled //执行时是否enable指标的计算和跟踪,默认true
metrics.rollingPercentile.timeInMilliseconds //设置rolling percentile window的时间,默认60000
metrics.rollingPercentile.numBuckets //设置rolling percentile window的numberBuckets。逻辑同上。默认6
metrics.rollingPercentile.bucketSize //如果bucket size=100,window=10s,若这10s里有500次执行,只有最后100次执行会被统计到bucket里去。增加该值会增加内存开销以及排序的开销。默认100
metrics.healthSnapshot.intervalInMilliseconds //记录health 快照(用来统计成功和错误绿)的间隔,默认500ms

//Request Context 相关参数
requestCache.enabled //默认true,需要重载getCacheKey(),返回null时不缓存
requestLog.enabled //记录日志到HystrixRequestLog,默认true

//Collapser Properties 相关参数
hystrix.collapser.default.maxRequestsInBatch //单次批处理的最大请求数,达到该数量触发批处理,默认Integer.MAX_VALUE
hystrix.collapser.default.timerDelayInMilliseconds //触发批处理的延迟,也可以为创建批处理的时间+该值,默认10
hystrix.collapser.default.requestCache.enabled //是否对HystrixCollapser.execute() and HystrixCollapser.queue()的cache,默认true

//ThreadPool 相关参数
//线程数默认值10适用于大部分情况(有时可以设置得更小),如果需要设置得更大,那有个基本得公式可以follow:
//requests per second at peak when healthy × 99th percentile latency in seconds + some breathing room
//每秒最大支撑的请求数 (99%平均响应时间 + 缓存值)
//比如:每秒能处理1000个请求,99%的请求响应时间是60ms,那么公式是:
//(0.060+0.012)

//基本得原则时保持线程池尽可能小,他主要是为了释放压力,防止资源被阻塞。
//当一切都是正常的时候,线程池一般仅会有1到2个线程激活来提供服务

hystrix.threadpool.default.coreSize //并发执行的最大线程数,默认10
hystrix.threadpool.default.maxQueueSize //BlockingQueue的最大队列数,当设为-1,会使用SynchronousQueue,值为正时使用LinkedBlcokingQueue。该设置只会在初始化时有效,之后不能修改threadpool的queue size,除非reinitialising thread executor。默认-1。
hystrix.threadpool.default.queueSizeRejectionThreshold //即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝。因为maxQueueSize不能被动态修改,这个参数将允许我们动态设置该值。if maxQueueSize == -1,该字段将不起作用
hystrix.threadpool.default.keepAliveTimeMinutes //如果corePoolSize和maxPoolSize设成一样(默认实现)该设置无效。如果通过plugin(https://github.com/Netflix/Hystrix/wiki/Plugins)使用自定义实现,该设置才有用,默认1.
hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds //线程池统计指标的时间,默认10000
hystrix.threadpool.default.metrics.rollingStats.numBuckets 将rolling //window划分为n个buckets,默认10

服务限流

在面对高并发的流量,如同秒杀业务时,将访问排队后一个一个经行处理。

后面使用alibaba的Sentinel说明

实时监控

在微服务架构中,Hystrix 除了实现容错外,还提供了实时监控功能。在服务调用时,Hystrix 会实时累积关于 HystrixCommand 的执行信息,比如每秒的请求数、成功数等。

下面我们来配置一个实时监控页面

1、新建项目:cloud-hystrix-dashboard9001

2、导入pom.xml

<dependencies>
    <!--新增hystrix dashboard-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        <version>2.2.8.RELEASE</version>
    </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>

3、创建application.yml

server:
  port: 9001
# 开启权限
hystrix:
  dashboard:
    proxy-stream-allow-list: "*"

4、主启动类:@EnableHystrixDashboard

package com.wyx.cloud;

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

@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardMain9001 {

    public static void main(String[] args) {
        SpringApplication.run(HystrixDashboardMain9001.class, args);
    }
}

5、启动程序访问测试:http://localhost:9001/hystrix

6、修改8001和80,检测是否有如下依赖,没有则添加

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

7、主启动类下注入以下bean

@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;
}

8、访问服务带有熔断的服务

9、访问http://localhost:9001/hystrix,填写监控入口。如下:

图表参数说明:

posted @ 2021-06-16 11:09  橘子有点甜  阅读(198)  评论(0编辑  收藏  举报