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项目官方做更多了解)