SpringCloud组件之Hystrix

简介: SpringCloud组件之Hystrix

在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性
hystrix

一、Hystrix宗旨和工作原理

Hystrix的宗旨:

  • 防止任何单个依赖项耗尽所有容器(如Tomcat)用户线程
  • 在任何可行的地方提供回退,以保护用户不受失败的影响
  • 使用隔离技术(如隔离板、泳道和断路器模式)来限制任何一个依赖项的影响
  • 通过近实时的度量、监视和警报来优化发现时间
  • 通过配置的低延迟传播来优化恢复时间
  • 避免在整个依赖客户端执行中出现故障,而不仅仅是在网络流量中

Hystrix工作原理

info
当需要完成某项任务时,通过 Hystrix 将任务包裹起来,交由 Hystrix 来完成任务,从而享受 Hystrix 带来保护

  • 1、构建命令

Hystrix 提供了两个Command, HystrixCommand 和 HystrixObservableCommand,可以使用这两个对象来包裹待执行的任务,Hystrix应用自己的一系列保护机制,在执行用户任务的各节点(执行前、执行后、异常、超时等)做一系列的事情

  • 2、执行命令
    有四种方式执行command
  • R execute():同步执行,从依赖服务得到单一结果对象
  • Future queue():异步执行,返回一个 Future 以便获取执行结果,也是单一结果对象
  • Observable observe():hot observable,创建Observable后会订阅Observable,可以返回多个结果
  • Observable toObservable():cold observable,返回一个Observable,只有订阅时才会执行,可以返回多个结果
  • 3、检查缓存

如果启用了 Hystrix Cache,任务执行前将先判断是否有相同命令执行的缓存。如果有则直接返回缓存的结果;如果没有缓存的结果,但启动了缓存,将缓存本次执行结果以供后续使用

  • 4、检查断路器是否打开

断路器(circuit-breaker)和保险丝类似,保险丝在发生危险时将会烧断以保护电路,而断路器可以在达到我们设定的阀值时触发短路(比如请求失败率达到50%),拒绝执行任何请求。如果断路器被打开,Hystrix 将不会执行命令,直接进入Fallback处理逻辑

  • 5、检查线程池/信号量情况

Hystrix 隔离方式有线程池隔离和信号量隔离。当使用Hystrix线程池时,Hystrix 默认为每个依赖服务分配10个线程,当10个线程都繁忙时,将拒绝执行命令。信号量同理

  • 6、执行具体的任务

通过HystrixObservableCommand.construct() 或者 HystrixCommand.run() 来运行用户真正的任务

  • 7、计算链路健康情况

每次开始执行command、结束执行command以及发生异常等情况时,都会记录执行情况,例如:成功、失败、拒绝以及超时等情况,会定期处理这些数据,再根据设定的条件来判断是否开启断路器

  • 8、命令失败时执行 Fallback 逻辑

在命令失败时执行用户指定的 Fallback 逻辑。上图中的断路、线程池拒绝、信号量拒绝、执行执行、执行超时都会进入 Fallback 处理

  • 9、返回执行结果

原始结果将以Observable形式返回,在返回给用户之前,会根据调用方式的不同做一些处理

更多详细的工作原理,可前往: How is Works

二、HystrixCommand注解

我们的配置都是基于 HystrixCommand 的,我们通过在方法上添加 @HystrixCommand 注解并配置注解的参数来实现配置,但有的时候一个类里面会有多个 Hystrix 方法,每个方法都是类似配置的话会冗余很多代码,这时候我们可以在类上使用 @DefaultProperties 注解来给整个类的 Hystrix 方法设置一个默认值。
参数介绍

  • commandKey: 用来标识一个 Hystrix 命令,默认会取被注解的方法名。需要注意:Hystrix 里同一个键的唯一标识并不包括 groupKey,建议取一个独一二无的名字,防止多个方法之间因为键重复而互相影响
  • groupKey:一组Hystrix命令的集合,统计、报告、默认取类名,可不配置
  • threadPoolKey:标识一个线程池,如果没设置会取groupKey,很多情况下都是同一个类内的方法共用一个线程池
  • commandProperties:与此命令相关的属性
  • threadPoolProperties:与线程池相关的属性
  • observableExcutionMode:当Hystrix命令被包装成RxJava的Observer异步执行时,此配置指定了Observable被执行的模式,默认是ObservableExecutionMode.EAGER, Obserable会在被创建后立刻执行,而ObservableExecutionMode.EAGER模式下,则会产生一个Observable被Subscribe执行,此配置项可以不配置
  • ignoreExceptions:默认Hystrix在执行方法时捕获到异常时执行回退,并统计失败率以修改熔断器的状态,而被忽略的异常则会直接抛到外层,不执行回退,也不影响熔断器的状态
  • raiseHystrixExceptions:当配置项包括 HystrixRuntimeException 时,所有的未被忽略的异常都会被包装成HystrixRuntimeException,配置其他种类的异常好像并没有什么影响
  • fallbackMethod:方法执行时容断、错误、超时会执行的回退方法,需要保证返回值一致

三、hystrix配置属性详解

Hystrix配置属性详解,所有属性默认都是default,如需针对某个服务,将default改为那个服务名即可

  1. Execution:控制HystrixCommand.run()如何运行
  2. Fallback:控制HystrixCommand.getFallback()如何运行
  3. Circuit Breadker:控制断路器的行为
  4. Metrics:捕获HystrixCommand和HystrixObervableCommand执行消息相关的配置属性
  5. Request Context:设置请求上下文的属性
  6. Collapser Properties:设置请求合并的属性
  7. Thread Pool Properties:设置线程池的属性

1、Execution

  • execution.isolation.strategy:表示Hystrix.command.run()执行时的隔离策略,有以下两种

    1. Thread:在单独的线程上执行,并发请求受线程池中的线程数限制
    2. SEMAPHORE:在调用线程上执行,并发请求量受信号量计数限制

在默认情况下,推荐HystrixCommands 使用 thread 隔离策略,HystrixObservableCommand 使用 semaphore 隔离策略。 只有在高并发(单个实例每秒达到几百个调用)的调用时,才需要修改HystrixCommands 的隔离策略为semaphore 。semaphore 隔离策略通常只用于非网络调用

hystrix.command.default.execution.isolation.strategy=
  • execution.isolation.thread.timeoutInMilliseconds:设置调用者执行的超时实际(单位毫秒),默认1000
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=
  • execution.isolation.thread.interruptOnTimeout:表示设置执行超时时,中断HystrixCommand.run() 的执行,默认true
hystrix.command.default.execution.isolation.thread.interruptOnTimeout=
  • execution.isolation.semaphore.maxConcurrentRequests:当HystrixCommand.run()使用SEMAPHORE隔离策略时,设置并发量,默认10
hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests=
  • execution.isolation.thread.interruptOnCancel:表示设置是否在取消任务执行时,中断HystrixCommand.run()执行,默认false
hystrix.command.default.execution.isolation.thread.interruptOnCancel=

2、Fallback

以下属性控制HystrixCommand.getFallback() 如何执行。这些属性对隔离策略THREAD 和SEMAPHORE都起作用

  • fallback.isolation.semaphore.maxConcurrentRequests:此属性设置从调用线程允许HystrixCommand.getFallback()方法允许的最大并发请求数 如果达到最大的并发量,则接下来的请求会被拒绝并且抛出异常,默认10
hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests=
  • fallback.enabled:是否开启fallback功能,默认true
hystrix.command.default.fallback.enabled=

3、Circuit Breaker

控制断路器的行为

  • circuitBreaker.enabled:是否开启断路器功能,默认true
hystrix.command.default.circuitBreaker.enabled=
  • circuitBreaker.requestVolumeThreshold:使断路器跳闸的最小请求数量,如果此属性值为20,则在窗口时间内(如10s内),如果只收到19个请求且都失败了,则断路器也不会开启。默认20
hystrix.command.default.circuitBreaker.requestVolumeThreshold=
  • circuitBreaker.errorThresholdPercentage:设置失败百分比的阈值。如果失败比率超过这个值,则断路器跳闸并且进入fallback逻辑,默认50
hystrix.command.default.circuitBreaker=
  • circuitBreaker.forceOpen:如果设置true,则强制使断路器跳闸,则会拒绝所有的请求.此值会覆盖circuitBreaker.forceClosed的值,默认false
hystrix.command.default.circuitBreaker.forceOpen=
  • circuitBreaker.forceClosed:如果设置true,则强制使断路器进行关闭状态,此时会允许执行所有请求,无论是否失败的次数达到circuitBreaker.errorThresholdPercentage值,默认false
hystrix.command.default.circuitBreaker.forceClosed=

4、Mertrics

捕获和HystrixCommand 和 HystrixObservableCommand 执行信息相关的配置属性

  • metrics.rollingStats.timeInMilliseconds:设置统计滚动窗口的时间长度如果此值为10s,将窗口分成10个桶,每个桶表示1s时间,默认10000
hystrix.command.default.metrics.rollingStats.timeInMilliseconds=
  • metrics.rollingStats.numBuckets:设置统计滚动窗口的桶数量,必须满足metrics.rollingStats.timeInMilliseconds % metrics.rollingStats.numBuckets == 0,否则异常,比如:1000/10,1000/20是正确的,1000/7是错的,高并发环境里,每个桶时间长度建议大于100ms,默认10
hystrix.command.default.metrics.rollingStats.numBuckets=
  • metrics.rollingPercentile.enabled:设置执行延迟是否被跟踪,并且被计算在失败百分比中。如果设置为false,则所有的统计数据返回-1,默认true
hystrix.command.default.metrics.rollingPercentile.enabled=
  • metrics.rollingPercentile.timeInMilliseconds:此属性设置统计滚动百分比窗口的持续时间,默认60000
hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds=
  • metrics.rollingPercentile.numBuckets:设置统计滚动百分比窗口的桶数量,以下配置必须成立,metrics.rollingPercentile.timeInMilliseconds % metrics.rollingPercentile.numBuckets == 0,否则异常,比如1000/10是对的,1000/7是错的,高并发情况下每个桶的时间长度建议大于1000ms,默认6
hystrix.command.default.metrics.rollingPercentile.numBuckets=
  • metrics.rollingPercentile.bucketSize:设置每个桶保存的执行时间的最大值。如果桶数量是100,统计窗口为10s,如果这10s里有500次执行,只有最后100次执行会被统计到bucket里去,默认100
hystrix.command.default.metrics.rollingPercentile.bucketSize=
  • metrics.healthSnapshot.intervalInMilliseconds:采样时间间隔
hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds=

5、Request Context

此属性控制HystrixCommand使用到的Hystrix的上下文

  • requestCache.enabled:是否开启请求缓存功能,默认true
hystrix.command.default.requestCache.enabled=
  • requestLog.enabled:是否开启日志,打印执行HystrixCommand的情况和事件,默认true
hystrix.command.default.requestLog.enabled=

6、Collapser Properties

设置请求合并的属性

  • maxRequestsInBatch:设置同时批量执行的请求的最大数量,默认Integer.MAX_VALUE
hystrix.collapser.default.maxRequestsInBatch=
  • timerDelayInMilliseconds:批量执行创建多久之后,再触发真正的请求,默认10
hystrix.collapser.default.timerDelayInMilliseconds=
  • requestCache.enabled:是否对HystrixCollapser.execute() 和 HystrixCollapser.queue()开启请求缓存,默认true
hystrix.collapser.default.requestCache.enabled=

7、Thread Pool Properties

设置Hystrix Commands的线程池行为,大部分情况线程数量是10。线程池数量的计算公式如下:最高峰时每秒的请求数量 × 99%命令执行时间 + 喘息空间,设置线程池数量的主要原则是保持线程池越小越好,因为它是减轻负载并防止资源在延迟发生时被阻塞的主要工具

  • coreSize:设置线程池的core的大小,默认10
hystrix.threadpool.default.coreSize=
  • maximumSize:设置最大的线程池的大小,只有设置allowMaximumSizeToDivergeFromCoreSize时,此值才起作用,默认10
hystrix.threadpool.default.maximumSize=
  • maxQueueSize:设置最大的BlockingQueue队列的值。如果设置-1,则使用SynchronousQueue队列,如果设置正数,则使用LinkedBlockingQueue队列,默认-1
hystrix.threadpool.default.maxQueueSize=
  • queueSizeRejectionThreshold:因为maxQueueSize值不能被动态修改,所有通过设置此值可以实现动态修改等待队列长度。即等待的队列的数量大于queueSizeRejectionThreshold时(但是没有达到maxQueueSize值),则开始拒绝后续的请求进入队列。如果设置-1,则属性不启作用,默认5
hystrix.threadpool.default.queueSizeRejectionThreshold=
  • keepAliveTimeMinutes:设置线程多久没有服务后,需要释放(maximumSize-coreSize )个线程,默认1
hystrix.threadpool.default.keepAliveTimeMinutes=
  • allowMaximumSizeToDivergeFromCoreSize:设置allowMaximumSizeToDivergeFromCoreSize值为true时,maximumSize才有作用,默认false
hystrix.threadpool.default.allowMaximumSizeToDivergeFromCoreSize=
  • metrics.rollingStats.timeInMilliseconds:设置滚动窗口的时间,默认10000
hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds=
  • metrics.rollingStats.numBuckets:设置滚动静态窗口分成的桶的数量,必须满足metrics.rollingStats.timeInMilliseconds % metrics.rollingStats.numBuckets == 0,默认值10,高并发情况下建议每个桶时间长度大于100ms
hystrix.threadpool.default.metrics.rollingStats.numBuckets=

四、Hystrix的使用

1、导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<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>cn.gjing</groupId>
    <artifactId>tools-httpclient</artifactId>
    <version>1.0.2</version>
</dependency>

2、启动类标注注解

/**
 * @author Gjing
 */
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class HystrixApplication {

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

3、编写service

@Service
public class TestService {

     // 此注解说明该方法要执行回退,fallback指定回退方法
    @HystrixCommand(fallbackMethod = "defaultFallback")
    public String hello() {
        HttpClient httpClient = new HttpClient();
        return httpClient.get("http://127.0.0.1:8090/test2", String.class);
    }

    // 回退方法
    public String defaultFallback() {
        return "no hello";
    }
}

4、编写Controller进行测试

/**
 * @author Gjing
 **/
@RestController
public class TestController {

    @Resource
    private TestService testService;

    @PostMapping("/test")
    public String test() {
        return testService.hello();
    }
}

5、目标服务的接口

因为hystrix默认超时是1秒,所以,我们在目标服务,加个线程休眠,大于1秒即可

/**
 * @author Gjing
 **/
@RestController
public class DemoController {

    @GetMapping("/test2")
    public String test2() throws InterruptedException {
        Thread.sleep(1000);
        return "ok";
    }
}

5、测试

超时进入回退方法,并返回了回退方法里的内容
1562046883_1_

三、Feign使用Hystrix

1、增加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2、启动类增加@EnableFeignClients注解

3、增加一个service和回退类

/**
 * @author Gjing
 * name为目标服务名,fallback为回退类
 **/
@FeignClient(name = "demo",fallback = FeignServiceFallbackImpl.class)
public interface FeignService {

    @RequestMapping(value = "/test2", method = RequestMethod.GET)
    String  test2();
}

/**
 * 回退类,实现feignService
 */
@Component
class FeignServiceFallbackImpl implements FeignService{
    @Override
    public String test2() {
        return "啊哦,出错了");
    }
}

4、编写Controller进行测试

/**
 * @author Gjing
 **/
@RestController
public class FeignController {

    @Resource
    private FeignService feignService;

    @PostMapping("/testFeign")
    public String testFeign() {
        return feignService.test();
    }
}

如果出错了,会进行回退
erro

四、使用监控面板dashBoard

1、增加依赖

<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>

2、启动类加上注解@EnableHystrixDashboard

3、配置文件

server:
  port: 8082
spring:
  application:
    name: hystrix-demo
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
# feign使用hystrix进行回退
feign:
  hystrix:
    enabled: true
# 端点管理 hystrixDashboard
management:
  endpoints:
    web:
      exposure:
        include: "*"

4、启动项目,并访问http://localhost:port/hystrix即可打开如下页面

d
通过主页面的文字介绍,可以知道,共支持三种不同的监控方式*

本文只讲解单体应用,因此我们在主页面输入http://localhost:8082/actuator/hystrix.stream即可访问,请求几次结果

re

界面解释

js

到此本文就结束了,篇幅较长,如哪里有字写错或单词打错,各位帮忙纠正,本项目源码:SpringCloud-Demo

目录
相关文章
|
1月前
|
负载均衡 Java API
Spring Cloud 面试题及答案整理,最新面试题
Spring Cloud 面试题及答案整理,最新面试题
138 1
|
1月前
|
Java Nacos Sentinel
Spring Cloud Alibaba 面试题及答案整理,最新面试题
Spring Cloud Alibaba 面试题及答案整理,最新面试题
214 0
|
3天前
|
Java 数据安全/隐私保护 Sentinel
微服务学习 | Spring Cloud 中使用 Sentinel 实现服务限流
微服务学习 | Spring Cloud 中使用 Sentinel 实现服务限流
|
4天前
|
Java API Nacos
第十二章 Spring Cloud Alibaba Sentinel
第十二章 Spring Cloud Alibaba Sentinel
16 0
|
4天前
|
监控 Java 微服务
第八章 Spring Cloud 之 Hystrix
第八章 Spring Cloud 之 Hystrix
|
4天前
|
监控 Java API
第七章 Spring Cloud 之 GateWay
第七章 Spring Cloud 之 GateWay
11 0
|
4天前
|
负载均衡 前端开发 Java
第六章 Spring Cloud 之 OpenFeign
第六章 Spring Cloud 之 OpenFeign
|
4天前
|
消息中间件 Java Nacos
第三章 Spring Cloud简介
第三章 Spring Cloud简介
12 0
|
4天前
|
Java Nacos 开发者
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
|
4天前
|
Dubbo Java 应用服务中间件
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架