Loading

Hystrix的核心源码

Hystrix 底层基于 RxJava,RxJava 是响应式编程开发库,因此Hystrix的整个实现策略简单说即:把一个HystrixCommand封装成一个Observable(待观察者),针对自身要实现的核心功能,对Observable进行各种装饰,并在订阅各步装饰的Observable,以便在指定事件到达时,添加自己的业务。

Hystrix主要有4种调用方式:

  toObservable() 方法 :未做订阅,只是返回一个Observable 。
  observe() 方法 :调用 #toObservable() 方法,并向 Observable 注册 rx.subjects.ReplaySubject发起订阅。
  queue() 方法 :调用 #toObservable() 方法的基础上,调用:Observable#toBlocking() 和BlockingObservable#toFuture() 返回 Future 对象
  execute() 方法 :调用 #queue() 方法的基础上,调用 Future#get() 方法,同步返回 #run() 的执行结果。

主要的执行逻辑:

  1. 每次调用创建一个新的HystrixCommand,把依赖调用封装在run()方法中.
  2. 执行execute()/queue做同步或异步调用.
  3. 判断熔断器(circuit-breaker)是否打开,如果打开跳到步骤8,进行降级策略,如果关闭进入步骤.
  4. 判断线程池/队列/信号量是否跑满,如果跑满进入降级步骤8,否则继续后续步骤.
  5. 调用HystrixCommand的run方法.运行依赖逻辑,依赖逻辑调用超时,进入步骤8.
  6. 判断逻辑是否调用成功。返回成功调用结果;调用出错,进入步骤8.
  7. 计算熔断器状态,所有的运行状态(成功, 失败, 拒绝,超时)上报给熔断器,用于统计从而判断熔断器状态.
  8. getFallback()降级逻辑。以下四种情况将触发getFallback调用:
    1. run()方法抛出非HystrixBadRequestException异常。
    2. run()方法调用超时
    3. 熔断器开启拦截调用
    4. 线程池/队列/信号量是否跑满
    5. 没有实现getFallback的Command将直接抛出异常,fallback降级逻辑调用成功直接返回,降级逻辑调用失败抛出异常.
  9. 返回执行成功结果 

HystrixCommand注解

在实际应用过程通过@HystrixCommand注解能够更加简单快速的实现Hystrix的应用,那么我们就直接从@HystrixCommand注解入手,其中包含了诸多参数配置,如执行隔离策略,线程池定义等,这些参数就不一一说明了,我们来看看其是如何实现服务降级的。 
public @interface HystrixCommand {
  String groupKey() default "";

  String commandKey() default "";

  String threadPoolKey() default "";

  String fallbackMethod() default "";

  HystrixProperty[] commandProperties() default {};

  HystrixProperty[] threadPoolProperties() default {};

  Class<? extends Throwable>[] ignoreExceptions() default {};

  ObservableExecutionMode observableExecutionMode() default
ObservableExecutionMode.EAGER;

  HystrixException[] raiseHystrixExceptions() default {};

  String defaultFallback() default "";
}
其定义了fallbackMethod方法名,正如其名,其提供了一个定义回退方法映射,在异常触发时此方法名对应的method将被触发执行,从而实现服务的降级。那么@HystrixCommand注解又是如何被执行的呢,我们找到 HystrixCommandAspect.java ,其切点定义如下 :
@Aspect
public class HystrixCommandAspect {
  private static final Map<HystrixCommandAspect.HystrixPointcutType,
HystrixCommandAspect.MetaHolderFactory> META_HOLDER_FACTORY_MAP;

  public HystrixCommandAspect() {
}

@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixC
ommand)")
  public void hystrixCommandAnnotationPointcut() {
  }

@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixC
ollapser)")
  public void hystrixCollapserAnnotationPointcut() {
  }

  @Around("hystrixCommandAnnotationPointcut() ||
hystrixCollapserAnnotationPointcut()")
  public Object methodsAnnotatedWithHystrixCommand(ProceedingJoinPoint
joinPoint) throws Throwable {
      //
  }
可以看到被 @HystrixCommand 注解的方法将会执行切面处理。

环绕通知增强

在HystrixCommandAspect的methodsAnnotatedWithHystrixCommand方法中我们可以看到如下:
  @Around("hystrixCommandAnnotationPointcut() ||
hystrixCollapserAnnotationPointcut()")
  public Object methodsAnnotatedWithHystrixCommand(ProceedingJoinPoint
joinPoint) throws Throwable {
      Method method = AopUtils.getMethodFromTarget(joinPoint);
      Validate.notNull(method, "failed to get method from joinPoint: %s", new
Object[]{joinPoint});
      if (method.isAnnotationPresent(HystrixCommand.class) &&
method.isAnnotationPresent(HystrixCollapser.class)) {
          throw new IllegalStateException("method cannot be annotated with
HystrixCommand and HystrixCollapser annotations at the same time");
      } else {
          HystrixCommandAspect.MetaHolderFactory metaHolderFactory =
(HystrixCommandAspect.MetaHolderFactory)META_HOLDER_FACTORY_MAP.get(HystrixComma
ndAspect.HystrixPointcutType.of(method));
          MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
          HystrixInvokable invokable =
HystrixCommandFactory.getInstance().create(metaHolder);
          ExecutionType executionType =
metaHolder.isCollapserAnnotationPresent() ?
metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();


          try {
              Object result;
              if (!metaHolder.isObservable()) {
                  result = CommandExecutor.execute(invokable, executionType,
metaHolder);
              } else {
                  result = this.executeObservable(invokable, executionType,
metaHolder);
}

              return result;
          } catch (HystrixBadRequestException var9) {
              throw var9.getCause();
          } catch (HystrixRuntimeException var10) {
              throw this.hystrixRuntimeExceptionToThrowable(metaHolder,
var10);
          }
      }
  }
此方法通过环绕通知的形式对目标方法进行增强,主要作用如下:
  HystrixInvokable:定义了后续真正执行HystrixCommand的GenericCommand实例
  定义metaHolder,包含了当前被注解方法的所有相关有效信息
  执行方法: 在进入执行体前,其有一个判断条件,判断其是否是一个Observable模式(在Hystrix中,其实现大量依赖RXJAVA,会无处不在的看到Observable,其是一种观察者模式的实现,具体可以到RxJava项目官方做更多了解)
posted @ 2021-07-28 08:57  1640808365  阅读(195)  评论(0编辑  收藏  举报