Hystrix解析(三)
executeCommandAndObserve
- 定义不同的回调,doOnNext、doOnCompleted、onErrorResumeNext、doOnEach。
- 调用executeCommandWithSpecifiedIsolation获得执行命令的Observable
- 若执行命令超时特性开启,调用 Observable.lift 方法实现执行命令超时功能
private Observable<R> executeCommandAndObserve(final AbstractCommand<R> _cmd) {
final HystrixRequestContext currentRequestContext = HystrixRequestContext.getContextForCurrentThread();
//Action和Func都是定义的一个动作,Action是无返回值,Func是有返回值
// doOnNext中的回调。即命令执行之前执行的操作
final Action1<R> markEmits = new Action1<R>() //...
// doOnCompleted中的回调。命令执行完毕后执行的操作
final Action0 markOnCompleted = new Action0() //...
// onErrorResumeNext中的回调。命令执行失败后的回退逻辑
final Func1<Throwable, Observable<R>> handleFallback = new Func1<Throwable, Observable<R>>() //...
// doOnEach中的回调。`Observable`每发射一个数据都会执行这个回调,设置请求上下文
final Action1<Notification<? super R>> setRequestContext = new Action1<Notification<? super R>>() //...
Observable<R> execution;
if (properties.executionTimeoutEnabled().get()) {
execution = executeCommandWithSpecifiedIsolation(_cmd)
.lift(new HystrixObservableTimeoutOperator<R>(_cmd));
} else {
execution = executeCommandWithSpecifiedIsolation(_cmd);
}
return execution.doOnNext(markEmits)
.doOnCompleted(markOnCompleted)
.onErrorResumeNext(handleFallback)
.doOnEach(setRequestContext);
}
executeCommandWithSpecifiedIsolation
这个方法首先是根据当前不同的资源隔离策略执行不同的逻辑,THREAD、SEMAPHORE。
private Observable<R> executeCommandWithSpecifiedIsolation(final AbstractCommand<R> _cmd) {
if (properties.executionIsolationStrategy().get() == ExecutionIsolationStrategy.THREAD) {
//...
} else {
//...
try {
executionHook.onRunStart(_cmd);
executionHook.onExecutionStart(_cmd);
return getUserExecutionObservable(_cmd); //the getUserExecutionObservable method already wraps sync exceptions, so this shouldn't throw
} catch (Throwable ex) {
//If the above hooks throw, then use that as the result of the run method
return Observable.error(ex);
}
}
});
}
}
getUserExecutionObservable
调用 getExecutionObservable 方法创建 命令执行Observable 。 getExecutionObservable 方法是个抽象方法, HystrixCommand 实现了该方法。
private Observable<R> getUserExecutionObservable(final AbstractCommand<R> _cmd) {
Observable<R> userObservable;
try {
userObservable = getExecutionObservable();
} catch (Throwable ex) {
// the run() method is a user provided implementation so can throw instead of using Observable.onError
// so we catch it here and turn it into Observable.error
userObservable = Observable.error(ex);
}
return userObservable
.lift(new ExecutionHookApplication(_cmd))
.lift(new DeprecatedOnRunHookApplication(_cmd));
}
HystrixCommand
调用 HystrixCommand.getExecutionObservable
方法创建命令执行Observable这里最终调用的是run方法,通过Observable.just, just是RxJava中的一个操作符,它可以接受一个或者多个参数来创建一个Observable对象。
而这个run()方法是一个抽象方法,在HystrixCommand中并没有实现,而是在子类中实现,而此时传递的cmd=GenricCommand正好实现了HystrixCommand,重写了run方法
final protected Observable<R> getExecutionObservable() {
return Observable.defer(new Func0<Observable<R>>() {
@Override
public Observable<R> call() {
try {
return Observable.just(run());
} catch (Throwable ex) {
return Observable.error(ex);
}
}
}).doOnSubscribe(new Action0() {
@Override
public void call() {
// Save thread on which we get subscribed so that we can interrupt it later if needed
executionThread.set(Thread.currentThread());
}
});
}
GenericCommand.run
这里的实现和我们前面自定义的 HystrixCommandService 实现是一样的,同样是集成HystrixCommand,重写run方法。这里也是如此。
- 首先调用 getCommandAction() 方法获取 CommandAction。
- 然后调用 MethodExecutionAction.execute 方法,传入 ExecutionType 参数。
protected Object run() throws Exception {
LOGGER.debug("execute command: {}", getCommandKey().name());
return process(new Action() {
@Override
Object execute() {
return getCommandAction().execute(getExecutionType());
}
});
}