SpringCloud源码解析之Hystrix


一、Hystrix介绍

Hystrix能够在依赖服务失效的情况下,通过隔离系统依赖服务的方式,防止服务级联失败;同时 Hystrix 提供失败回滚机制,使系统能够更快地从异常中恢复


二、预备知识

1、@HystrixCommand详解

  • groupKey:分组名称,Hystrix会根据不同的分组来统计命令的告警及仪表盘信息,默认注解方法类的名称;
  • commandKey:命令名称,用于区分不同的命令;
  • threadPoolKey:线程池名称,用于划分线程池,线程池键用来指定命令执行的HystrixThreadPool;
  • fallbackMethod:指定服务降级处理方法,定义回退方法的名称,此方法必须和hystrix的执行方法在相同类中;
  • ignoreExceptions:定义忽略某些异常,不发生服务降级;
  • commandProperties:配置自定义hystrix命令的参数;

一般来说,对于 HystrixCommand 的配置,仅需要关注 fallbackMethod 方法,当然如果对命令和线程有特定需要,可以进行额外的配置。
在这里插入图片描述

2、@HystrixCollapser的常用属性

微服务系统中的服务间通信,需要通过远程调用来实现,随着调用次数越来越多,占用线程资源也会越来越多。Hystrix中提供了@HystrixCollapser用于合并请求,从而达到减少通信消耗及线程数量的效果,使用@HystrixCollapser实现请求合并,所有对某个接口的的多次调用都会转化为对该接口的单次调用。

  • batchMethod:用于设置请求合并的方法;
  • collapserProperties:请求合并属性,用于控制实例属性;
  • timerDelayInMilliseconds:collapserProperties中的属性,用于控制每隔多少时间的请求合并为一次请求;

3、Hystrix的请求缓存

当系统并发量越来越大时,我们需要使用缓存来优化系统,达到减轻并发请求线程数,提供响应速度的效果。

  • @CacheResult:开启缓存,默认所有参数作为缓存的key,cacheKeyMethod可以通过返回String类型的方法指定key
  • @CacheKey:指定缓存的key,可以指定参数或指定参数中的属性值为缓存key,cacheKeyMethod还可以通过返回String类型的方法指定;
  • @CacheRemove:移除缓存,需要指定commandKey。
@CacheResult(cacheKeyMethod = "getCacheKey")
@HystrixCommand(fallbackMethod = "getDefaultUser", commandKey = "getUserCache")

在缓存使用过程中,我们需要在每次使用缓存的请求前后对HystrixRequestContext进行初始化和关闭,否则会出现如下异常:
建议使用:@Cleanup

  @Cleanup HystrixRequestContext context = HystrixRequestContext.initializeContext();

4、Hystrix的配置

4.1、全局配置


# 开启Feign下面的Hystrix功能
feign.hystrix.enabled=true
# 是否开启服务降级
hystrix.command.default.fallback.enabled=true

# 全局超时
hystrix.command.default.execution.timeout.enabled=true
# 超时时间
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=1000
# 超时以后终止线程
hystrix.command.default.execution.isolation.thread.interruptOnTimeout=true
# 取消的时候终止线程
hystrix.command.default.execution.isolation.thread.interruptOnFutureCancel=true


# 熔断的前提条件(请求的数量),在一定的时间窗口内,请求达到5个以后,才开始进行熔断判断
hystrix.command.default.circuitBreaker.requestVolumeThreshold=5
# 超过50%的失败请求,则熔断开关开启
hystrix.command.default.circuitBreaker.errorThresholdPercentage=50
# 当熔断开启以后,经过多少秒再进入半开状态
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=15000
# 配置时间窗口
hystrix.command.default.metrics.rollingStats.timeInMilliseconds=20000

hystrix.command.default.circuitBreaker.enabled=true
# 强制开启熔断开关
hystrix.command.default.circuitBreaker.forceOpen=false
# 强制关闭熔断开关
hystrix.command.default.circuitBreaker.forceClosed=false

参数说明英文地址:https://github.com/Netflix/Hystrix/wiki/Configuration

4.2、服务方法的配置

使用@HystrixCommand注解对对应的接口服务进行配置。
参数说明英文地址:https://github.com/Netflix/Hystrix/wiki/Configuration

三、源码解析

1. 实现fallback

1.1 从注解HystrixCommand进入到
在这里插入图片描述
2.2、通过HystrixCommand找到HystrixCommandAspect.java
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
进入create()方法

public HystrixInvokable create(MetaHolder metaHolder) {
     HystrixInvokable executable;
     if (metaHolder.isCollapserAnnotationPresent()) {
         executable = new CommandCollapser(metaHolder);
     } else if (metaHolder.isObservable()) {
         executable = new GenericObservableCommand(HystrixCommandBuilderFactory.getInstance().create(metaHolder));
     } else {
         executable = new GenericCommand(HystrixCommandBuilderFactory.getInstance().create(metaHolder));
     }
     return executable;
 }

MetaHolderFactory的构造
在这里插入图片描述
在这里插入图片描述

再进入到result = CommandExecutor.execute(invokable, executionType, metaHolder);这个execute的方法中:
在这里插入图片描述
executionType决定了最终的执行方式,如下

  • execute():同步执行,从依赖的服务返回一个单一的结果对象,或是在发生错误的时候抛出异常;
  • queue():异步执行,直接返回一个Future对象,其中包含了服务执行结束时要返回的单一结果对象;
  • observe():返回Observable对象,它代表了操作的多个结果,他是一个Hot Observable;
  • toObservable():同样返回Observable对象,也代表了操作的多个结果,但其返回的是一个Cold Observable;

进入execute()方法
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2. 实现requestCache的存储和获取

HystrixRequestCache的定义如下:通过ConcurrentHashMap来保证线程安全
在这里插入图片描述

根据AbstractCommand的构造函数,可以发现requestCache的构造方法:
HystrixPlugins获取concurrencyStrategy并发策略,
从而实例化了HystrixRequestCache实例requestCache
在这里插入图片描述

未完待续。。。


版权声明:本文为u013427308原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。