• 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());
            }
        });
    }
    

    关系图

  • 相关阅读:
    MyEclipse中快速查看错误
    MyEclipse中快速跳转到指定行号位置
    MyEclipse关闭当前正在编辑的页面
    dict、defaultdict 和 OrderedDict 比较
    过滤器的使用
    cookie和session
    session的使用
    Java的常量和变量
    Java面向对象
    Java方法
  • 原文地址:https://www.cnblogs.com/snail-gao/p/14137583.html
Copyright © 2020-2023  润新知