今天我们分析Hystrix 的源码:废话少说,从jar包开始:
1、点击进入 HystrixCircuitBreakerConfiguration 创建 hystrixCommand 注解的切面类
2、找到HystrixCommand 注解,发现对应业务接口上的注解,说明这个业务类会生成代理
客户端调用主要走这个方法:
3、点击CommandExecutor进入:
先看同步方法:
进入:HystrixCommand 核心类,后面的fegin和zuul 组件都用到这个类,调用同步阻塞方法
点击query方法:
点击toObservable方法进入 AbstractCommand 里面有多个匿名内部类,属于Rsjava 代码写法风格
点击 applyHystrixSemantics 调用匿名类 里面的call方法
进入发现allRequest()方法 是是否允许请求正常的业务方法,此为熔断的功能,比如:
4、进入:熔断器是否开启(配置)、是否关闭(配置)、没有开启、允许单个请求; 点击isOpen(),最大请求数、错误百分比、原子操作、记录时间; 点击allowSingleTest(),单个测试请求 对比时间
返回刚才源代码:
private Observable<R> applyHystrixSemantics(final AbstractCommand<R> _cmd) {
// mark that we're starting execution on the ExecutionHook
// if this hook throws an exception, then a fast-fail occurs with no fallback. No state is left inconsistent
executionHook.onStart(_cmd);
/* determine if we're allowed to execute */
if (circuitBreaker.allowRequest()) {
final TryableSemaphore executionSemaphore = getExecutionSemaphore();//信号量
final AtomicBoolean semaphoreHasBeenReleased = new AtomicBoolean(false);
final Action0 singleSemaphoreRelease = new Action0() {
@Override
public void call() {
if (semaphoreHasBeenReleased.compareAndSet(false, true)) {
executionSemaphore.release();
}
}
};
final Action1<Throwable> markExceptionThrown = new Action1<Throwable>() {
@Override
public void call(Throwable t) {
eventNotifier.markEvent(HystrixEventType.EXCEPTION_THROWN, commandKey);
}
};
if (executionSemaphore.tryAcquire()) {//获取请求
try {
/* used to track userThreadExecutionTime */
executionResult = executionResult.setInvocationStartTime(System.currentTimeMillis());
return executeCommandAndObserve(_cmd)//信号量执行的主方法
.doOnError(markExceptionThrown)
.doOnTerminate(singleSemaphoreRelease)
.doOnUnsubscribe(singleSemaphoreRelease);
} catch (RuntimeException e) {
return Observable.error(e);
}
} else {
return handleSemaphoreRejectionViaFallback();//信号量降级方法
}
} else {
return handleShortCircuitViaFallback();//降级方法
}
}
5、点击 getExecutionSemaphore 找到信号量配置,和开发代码对比
信号量的值是否达到最大
点击 executeCommandAndObserve 方法:里面有超时时间设置
点击executeCommandWithSpecifiedIsolation 线程池策略:
ctrl+t 对这个方法 getExecutionObservable,找到核心钩子方法
5、进入反射调用的方法:
这条核心路执行完了,信号量和线程池策略实现思路大同小异。
点击wrapWithAllOnNextHooks 调用匿名类里面的call方法:
3、线程池的创建及超时控制
这里创建了线程其他的,比如熔断器开启,线程池,信号量都满了,则会走到降级方法
这里也是会反射调用到 fallback 方法,fallback 降级方法也是有信号量和线程池的大小控制 的,也就是信号量或线程池是多少大小,fallback 降级方法也会接收多少降级的请求。
Hystrix 源码分析结束,明天我们分析Fegin的源码,敬请期待。