• hystrix源码之AbstractCommand


    AbstractCommand

       HystrixCommand和HystrixObservableCommand的父类。每个command对应一个HystrixCommandKey、HystrixThreadPoolKey和HystrixCommandGroupKey。内部有HystrixCircuitBreaker、HystrixThreadPool、HystrixCommandProperties、HystrixCommandMetrics、HystrixCommandExecutionHook、HystrixConcurrencyStrategy、HystrixRequestCache、HystrixRequestLog、HystrixEventNotifier组件来实现各个功能。

    构造函数

      创建时,首先初始化内部的各个组件对象。

    protected AbstractCommand(HystrixCommandGroupKey group, HystrixCommandKey key, HystrixThreadPoolKey threadPoolKey, HystrixCircuitBreaker circuitBreaker, HystrixThreadPool threadPool,
                HystrixCommandProperties.Setter commandPropertiesDefaults, HystrixThreadPoolProperties.Setter threadPoolPropertiesDefaults,
                HystrixCommandMetrics metrics, TryableSemaphore fallbackSemaphore, TryableSemaphore executionSemaphore,
                HystrixPropertiesStrategy propertiesStrategy, HystrixCommandExecutionHook executionHook) {
            this.commandGroup = initGroupKey(group);
            this.commandKey = initCommandKey(key, getClass());
            this.properties = initCommandProperties(this.commandKey, propertiesStrategy, commandPropertiesDefaults);
            this.threadPoolKey = initThreadPoolKey(threadPoolKey, this.commandGroup, this.properties.executionIsolationThreadPoolKeyOverride().get());
            this.metrics = initMetrics(metrics, this.commandGroup, this.threadPoolKey, this.commandKey, this.properties);
            this.circuitBreaker = initCircuitBreaker(this.properties.circuitBreakerEnabled().get(), circuitBreaker, this.commandGroup, this.commandKey, this.properties, this.metrics);
            this.threadPool = initThreadPool(threadPool, this.threadPoolKey, threadPoolPropertiesDefaults);
            //Strategies from plugins
            this.eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
            this.concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
         //开始commandpublisher HystrixMetricsPublisherFactory.createOrRetrievePublisherForCommand(
    this.commandKey, this.commandGroup, this.metrics, this.circuitBreaker, this.properties); this.executionHook = initExecutionHook(executionHook); this.requestCache = HystrixRequestCache.getInstance(this.commandKey, this.concurrencyStrategy); this.currentRequestLog = initRequestLog(this.properties.requestLogEnabled().get(), this.concurrencyStrategy); /* 设置fallback的并发量 */ this.fallbackSemaphoreOverride = fallbackSemaphore; /* 设置excution的并发量 */ this.executionSemaphoreOverride = executionSemaphore; }

      通过HystrixPropertiesFactory获得指定commandKey的HystrixCommandProperties。

    private static HystrixCommandProperties initCommandProperties(HystrixCommandKey commandKey, HystrixPropertiesStrategy propertiesStrategy, HystrixCommandProperties.Setter commandPropertiesDefaults) {
            if (propertiesStrategy == null) {
                return HystrixPropertiesFactory.getCommandProperties(commandKey, commandPropertiesDefaults);
            } else {
                // used for unit testing
                return propertiesStrategy.getCommandProperties(commandKey, commandPropertiesDefaults);
            }
        }

      通过HystrixCommandMetrics获得指定commandKey的HystrixCommandMetrics。

    private static HystrixCommandMetrics initMetrics(HystrixCommandMetrics fromConstructor, HystrixCommandGroupKey groupKey,
                                                         HystrixThreadPoolKey threadPoolKey, HystrixCommandKey commandKey,
                                                         HystrixCommandProperties properties) {
            if (fromConstructor == null) {
                return HystrixCommandMetrics.getInstance(commandKey, groupKey, threadPoolKey, properties);
            } else {
                return fromConstructor;
            }
        }

      通过HystrixCircuitBreaker.Factory获得指定commandKey的HystrixCircuitBreaker。

    private static HystrixCircuitBreaker initCircuitBreaker(boolean enabled, HystrixCircuitBreaker fromConstructor,
                                                                HystrixCommandGroupKey groupKey, HystrixCommandKey commandKey,
                                                                HystrixCommandProperties properties, HystrixCommandMetrics metrics) {
            if (enabled) {
                if (fromConstructor == null) {
                    // get the default implementation of HystrixCircuitBreaker
                    return HystrixCircuitBreaker.Factory.getInstance(commandKey, groupKey, properties, metrics);
                } else {
                    return fromConstructor;
                }
            } else {
                return new NoOpCircuitBreaker();
            }
        }

      通过HystrixThreadPool.Factory获得指定threadPoolKey的HystrixThreadPool。

    private static HystrixThreadPool initThreadPool(HystrixThreadPool fromConstructor, HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties.Setter threadPoolPropertiesDefaults) {
            if (fromConstructor == null) {
                // get the default implementation of HystrixThreadPool
                return HystrixThreadPool.Factory.getInstance(threadPoolKey, threadPoolPropertiesDefaults);
            } else {
                return fromConstructor;
            }
        }

      通过HystrixPlugins获得自定义插架HystrixCommandExecutionHook。

    private static HystrixCommandExecutionHook initExecutionHook(HystrixCommandExecutionHook fromConstructor) {
            if (fromConstructor == null) {
                return new ExecutionHookDeprecationWrapper(HystrixPlugins.getInstance().getCommandExecutionHook());
            } else {
                // used for unit testing
                if (fromConstructor instanceof ExecutionHookDeprecationWrapper) {
                    return fromConstructor;
                } else {
                    return new ExecutionHookDeprecationWrapper(fromConstructor);
                }
            }
        }

      通过HystrixPlugins获得自定义插架HystrixEventNotifier、HystrixConcurrencyStrategy。

    this.eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
    this.concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();

      通过HystrixRequestCache获得指定commandKey的HystrixRequestCache。

    this.requestCache = HystrixRequestCache.getInstance(this.commandKey, this.concurrencyStrategy);

      通过HystrixRequestLog获得当前的HystrixRequestLog。

    private static HystrixRequestLog initRequestLog(boolean enabled, HystrixConcurrencyStrategy concurrencyStrategy) {
            if (enabled) {
                /* store reference to request log regardless of which thread later hits it */
                return HystrixRequestLog.getCurrentRequest(concurrencyStrategy);
            } else {
                return null;
            }
        }

     observe方法

       使用了ReplaySubject缓存了toObservable的消息,使得执行后再监听也可以收到所有消息。

    public Observable<R> observe() {
            // us a ReplaySubject to buffer the eagerly subscribed-to Observable
            ReplaySubject<R> subject = ReplaySubject.create();
            // eagerly kick off subscription
            final Subscription sourceSubscription = toObservable().subscribe(subject);
            // return the subject that can be subscribed to later while the execution has already started
            return subject.doOnUnsubscribe(new Action0() {
                @Override
                public void call() {
                    sourceSubscription.unsubscribe();
                }
            });
        }

     toObservable方法

    public Observable<R> toObservable() {
         ...
    return Observable.defer(new Func0<Observable<R>>() { @Override public Observable<R> call() { /* 每个command对象,只能被执行一次 */ if (!commandState.compareAndSet(CommandState.NOT_STARTED, CommandState.OBSERVABLE_CHAIN_CREATED)) { IllegalStateException ex = new IllegalStateException("This instance can only be executed once. Please instantiate a new instance."); //TODO make a new error type for this throw new HystrixRuntimeException(FailureType.BAD_REQUEST_EXCEPTION, _cmd.getClass(), getLogMessagePrefix() + " command executed multiple times - this is not permitted.", ex, null); } commandStartTimestamp = System.currentTimeMillis();          //如果开启了记录请求,则向HystrixRequestLog添加执行命令 if (properties.requestLogEnabled().get()) { // log this command execution regardless of what happened if (currentRequestLog != null) { currentRequestLog.addExecutedCommand(_cmd); } }
             //是否开启缓存,如果开启缓存并且实现了getCacheKey方法,则首先从HystrixRequestCache获取结果数据
    final boolean requestCacheEnabled = isRequestCachingEnabled(); final String cacheKey = getCacheKey(); /* try from cache first */ if (requestCacheEnabled) { HystrixCommandResponseFromCache<R> fromCache = (HystrixCommandResponseFromCache<R>) requestCache.get(cacheKey); if (fromCache != null) { isResponseFromCache = true; return handleRequestCacheHitAndEmitValues(fromCache, _cmd); } }          //执行命令返回结果 Observable<R> hystrixObservable = Observable.defer(applyHystrixSemantics) .map(wrapWithAllOnNextHooks); Observable<R> afterCache;
                  
    // 是否开启缓存,如果开启缓存并且实现了getCacheKey方法,将结果放到HystrixRequestCache if (requestCacheEnabled && cacheKey != null) { // wrap it for caching HystrixCachedObservable<R> toCache = HystrixCachedObservable.from(hystrixObservable, _cmd); HystrixCommandResponseFromCache<R> fromCache = (HystrixCommandResponseFromCache<R>) requestCache.putIfAbsent(cacheKey, toCache); if (fromCache != null) { // another thread beat us so we'll use the cached value instead toCache.unsubscribe(); isResponseFromCache = true; return handleRequestCacheHitAndEmitValues(fromCache, _cmd); } else { // we just created an ObservableCommand so we cast and return it afterCache = toCache.toObservable(); } } else { afterCache = hystrixObservable; } return afterCache .doOnTerminate(terminateCommandCleanup) // perform cleanup once (either on normal terminal state (this line), or unsubscribe (next line)) .doOnUnsubscribe(unsubscribeCommandCleanup) // perform cleanup once .doOnCompleted(fireOnCompletedHook); } }); }

       在获取缓存结束后,需要更新command状态,记录执行时间,输出metrics,发送消息。

    private Observable<R> handleRequestCacheHitAndEmitValues(final HystrixCommandResponseFromCache<R> fromCache, final AbstractCommand<R> _cmd) {
            try {
                executionHook.onCacheHit(this);
            } catch (Throwable hookEx) {
                logger.warn("Error calling HystrixCommandExecutionHook.onCacheHit", hookEx);
            }
    
            return fromCache.toObservableWithStateCopiedInto(this)
                    .doOnTerminate(new Action0() {
                        @Override
                        public void call() {
                            if (commandState.compareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.TERMINAL)) {
                                cleanUpAfterResponseFromCache(false); //user code never ran
                            } else if (commandState.compareAndSet(CommandState.USER_CODE_EXECUTED, CommandState.TERMINAL)) {
                                cleanUpAfterResponseFromCache(true); //user code did run
                            }
                        }
                    })
                    .doOnUnsubscribe(new Action0() {
                        @Override
                        public void call() {
                            if (commandState.compareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.UNSUBSCRIBED)) {
                                cleanUpAfterResponseFromCache(false); //user code never ran
                            } else if (commandState.compareAndSet(CommandState.USER_CODE_EXECUTED, CommandState.UNSUBSCRIBED)) {
                                cleanUpAfterResponseFromCache(true); //user code did run
                            }
                        }
                    });
        }
    
        private void cleanUpAfterResponseFromCache(boolean commandExecutionStarted) {
            Reference<TimerListener> tl = timeoutTimer.get();
            if (tl != null) {
                tl.clear();
            }
    
            final long latency = System.currentTimeMillis() - commandStartTimestamp;
            executionResult = executionResult
                    .addEvent(-1, HystrixEventType.RESPONSE_FROM_CACHE)
                    .markUserThreadCompletion(latency)
                    .setNotExecutedInThread();
            ExecutionResult cacheOnlyForMetrics = ExecutionResult.from(HystrixEventType.RESPONSE_FROM_CACHE)
                    .markUserThreadCompletion(latency);
            metrics.markCommandDone(cacheOnlyForMetrics, commandKey, threadPoolKey, commandExecutionStarted);
            eventNotifier.markEvent(HystrixEventType.RESPONSE_FROM_CACHE, commandKey);
        }

      在如果不是通过缓存在结束后,也需要更新command状态,记录执行时间,输出metrics,发送消息。

    final Action0 terminateCommandCleanup = new Action0() {
    
                @Override
                public void call() {
                    if (_cmd.commandState.compareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.TERMINAL)) {
                        handleCommandEnd(false); //user code never ran
                    } else if (_cmd.commandState.compareAndSet(CommandState.USER_CODE_EXECUTED, CommandState.TERMINAL)) {
                        handleCommandEnd(true); //user code did run
                    }
                }
            };
            final Action0 unsubscribeCommandCleanup = new Action0() {
                @Override
                public void call() {
                    circuitBreaker.markNonSuccess();
                    if (_cmd.commandState.compareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.UNSUBSCRIBED)) {
                        if (!_cmd.executionResult.containsTerminalEvent()) {
                            _cmd.eventNotifier.markEvent(HystrixEventType.CANCELLED, _cmd.commandKey);
                            try {
                                executionHook.onUnsubscribe(_cmd);
                            } catch (Throwable hookEx) {
                                logger.warn("Error calling HystrixCommandExecutionHook.onUnsubscribe", hookEx);
                            }
                            _cmd.executionResultAtTimeOfCancellation = _cmd.executionResult
                                    .addEvent((int) (System.currentTimeMillis() - _cmd.commandStartTimestamp), HystrixEventType.CANCELLED);
                        }
                        handleCommandEnd(false); //user code never ran
                    } else if (_cmd.commandState.compareAndSet(CommandState.USER_CODE_EXECUTED, CommandState.UNSUBSCRIBED)) {
                        if (!_cmd.executionResult.containsTerminalEvent()) {
                            _cmd.eventNotifier.markEvent(HystrixEventType.CANCELLED, _cmd.commandKey);
                            try {
                                executionHook.onUnsubscribe(_cmd);
                            } catch (Throwable hookEx) {
                                logger.warn("Error calling HystrixCommandExecutionHook.onUnsubscribe", hookEx);
                            }
                            _cmd.executionResultAtTimeOfCancellation = _cmd.executionResult
                                    .addEvent((int) (System.currentTimeMillis() - _cmd.commandStartTimestamp), HystrixEventType.CANCELLED);
                        }
                        handleCommandEnd(true); //user code did run
                    }
                }
            };
            final Action0 fireOnCompletedHook = new Action0() {
                @Override
                public void call() {
                    try {
                        executionHook.onSuccess(_cmd);
                    } catch (Throwable hookEx) {
                        logger.warn("Error calling HystrixCommandExecutionHook.onSuccess", hookEx);
                    }
                }
            };
            private void handleCommandEnd(boolean commandExecutionStarted) {
                Reference<TimerListener> tl = timeoutTimer.get();
                if (tl != null) {
                    tl.clear();
                }
    
                long userThreadLatency = System.currentTimeMillis() - commandStartTimestamp;
                executionResult = executionResult.markUserThreadCompletion((int) userThreadLatency);
                if (executionResultAtTimeOfCancellation == null) {
                    metrics.markCommandDone(executionResult, commandKey, threadPoolKey, commandExecutionStarted);
                } else {
                    metrics.markCommandDone(executionResultAtTimeOfCancellation, commandKey, threadPoolKey, commandExecutionStarted);
                }
    
                if (endCurrentThreadExecutingCommand != null) {
                    endCurrentThreadExecutingCommand.call();
                }
            }

       如果没有获取到缓存,则需要执行命令获得结果。命令执行流程如下:

    private Observable<R> applyHystrixSemantics(final AbstractCommand<R> _cmd) {// executionHook调用
            executionHook.onStart(_cmd);
            /* determine if we're allowed to execute */
            if (circuitBreaker.attemptExecution()) { //使用熔断器判断是否熔断
                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();//超过并发信号量fallback
                }
            } else {
                return handleShortCircuitViaFallback();//执行熔断fallback
            }
        }

     executeCommandAndObserve方法

     调用命令方法执行,并对执行的各种事件进行响应。

    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);

      命令返回数据时

    final Action1<R> markEmits = new Action1<R>() {
                @Override
                public void call(R r) {
                    if (shouldOutputOnNextEvents()) {
                        executionResult = executionResult.addEvent(HystrixEventType.EMIT);
                        eventNotifier.markEvent(HystrixEventType.EMIT, commandKey);//发送emit事件
                    }
                    if (commandIsScalar()) {
                        long latency = System.currentTimeMillis() - executionResult.getStartTimestamp();
                        eventNotifier.markEvent(HystrixEventType.SUCCESS, commandKey);//发送SUCCESS事件
                        executionResult = executionResult.addEvent((int) latency, HystrixEventType.SUCCESS);
                        eventNotifier.markCommandExecution(getCommandKey(), properties.executionIsolationStrategy().get(), (int) latency, executionResult.getOrderedList());
                        circuitBreaker.markSuccess();
                    }
                }
            };

       命令完成时

    final Action0 markOnCompleted = new Action0() {
                @Override
                public void call() {
                    if (!commandIsScalar()) {
                        long latency = System.currentTimeMillis() - executionResult.getStartTimestamp();
                        eventNotifier.markEvent(HystrixEventType.SUCCESS, commandKey);
                        executionResult = executionResult.addEvent((int) latency, HystrixEventType.SUCCESS);
                        eventNotifier.markCommandExecution(getCommandKey(), properties.executionIsolationStrategy().get(), (int) latency, executionResult.getOrderedList());
                        circuitBreaker.markSuccess();
                    }
                }
            };

      命令出现异常时

    final Func1<Throwable, Observable<R>> handleFallback = new Func1<Throwable, Observable<R>>() {
                @Override
                public Observable<R> call(Throwable t) {
                    circuitBreaker.markNonSuccess();
                    Exception e = getExceptionFromThrowable(t);
                    executionResult = executionResult.setExecutionException(e);
                    if (e instanceof RejectedExecutionException) {
                        return handleThreadPoolRejectionViaFallback(e);
                    } else if (t instanceof HystrixTimeoutException) {
                        return handleTimeoutViaFallback();
                    } else if (t instanceof HystrixBadRequestException) {
                        return handleBadRequestByEmittingError(e);
                    } else {
                        /*
                         * Treat HystrixBadRequestException from ExecutionHook like a plain HystrixBadRequestException.
                         */
                        if (e instanceof HystrixBadRequestException) {
                            eventNotifier.markEvent(HystrixEventType.BAD_REQUEST, commandKey);
                            return Observable.error(e);
                        }
                        return handleFailureViaFallback(e);
                    }
                }
            };

    handleThreadPoolRejectionViaFallback、handleTimeoutViaFallback、handleBadRequestByEmittingError、handleFailureViaFallback地层都调用了getFallbackOrThrowException方法。

    private Observable<R> handleThreadPoolRejectionViaFallback(Exception underlying) {
            eventNotifier.markEvent(HystrixEventType.THREAD_POOL_REJECTED, commandKey);
            threadPool.markThreadRejection();
            return getFallbackOrThrowException(this, HystrixEventType.THREAD_POOL_REJECTED, FailureType.REJECTED_THREAD_EXECUTION, "could not be queued for execution", underlying);
        }
        private Observable<R> handleTimeoutViaFallback() {
            return getFallbackOrThrowException(this, HystrixEventType.TIMEOUT, FailureType.TIMEOUT, "timed-out", new TimeoutException());
        }
        private Observable<R> handleBadRequestByEmittingError(Exception underlying) {
            Exception toEmit = underlying;
            try {
                long executionLatency = System.currentTimeMillis() - executionResult.getStartTimestamp();
                eventNotifier.markEvent(HystrixEventType.BAD_REQUEST, commandKey);
                executionResult = executionResult.addEvent((int) executionLatency, HystrixEventType.BAD_REQUEST);
                Exception decorated = executionHook.onError(this, FailureType.BAD_REQUEST_EXCEPTION, underlying);
                if (decorated instanceof HystrixBadRequestException) {
                    toEmit = decorated;
                } else {
                    logger.warn("ExecutionHook.onError returned an exception that was not an instance of HystrixBadRequestException so will be ignored.", decorated);
                }
            } catch (Exception hookEx) {
                logger.warn("Error calling HystrixCommandExecutionHook.onError", hookEx);
            }
            return Observable.error(toEmit);
        }
    
        private Observable<R> handleFailureViaFallback(Exception underlying) {// report failure
            eventNotifier.markEvent(HystrixEventType.FAILURE, commandKey);
            // record the exception
            executionResult = executionResult.setException(underlying);
            return getFallbackOrThrowException(this, HystrixEventType.FAILURE, FailureType.COMMAND_EXCEPTION, "failed", underlying);
        }

     getFallbackOrThrowException

      核心就是调用用户定义的fallback方法,并在各自情况下调用eventNotifier事件和返回executionResult。

    ...
    if (fallbackSemaphore.tryAcquire()) {
                        try {
                            if (isFallbackUserDefined()) {
                                executionHook.onFallbackStart(this);
                                fallbackExecutionChain = getFallbackObservable();
                            } else {
                                //same logic as above without the hook invocation
                                fallbackExecutionChain = getFallbackObservable();
                            }
                        } catch (Throwable ex) {
                            //If hook or user-fallback throws, then use that as the result of the fallback lookup
                            fallbackExecutionChain = Observable.error(ex);
                        }
    
                        return fallbackExecutionChain
                                .doOnEach(setRequestContext)
                                .lift(new FallbackHookApplication(_cmd))
                                .doOnNext(markFallbackEmit)
                                .doOnCompleted(markFallbackCompleted)
                                .onErrorResumeNext(handleFallbackError)
                                .doOnTerminate(singleSemaphoreRelease)
                                .doOnUnsubscribe(singleSemaphoreRelease);
                    } else {
                       return handleFallbackRejectionByEmittingError();
                    }
    ...

    timeout实现

    private static class HystrixObservableTimeoutOperator<R> implements Operator<R, R> {
    
            final AbstractCommand<R> originalCommand;
    
            public HystrixObservableTimeoutOperator(final AbstractCommand<R> originalCommand) {
                this.originalCommand = originalCommand;
            }
    
            @Override
            public Subscriber<? super R> call(final Subscriber<? super R> child) {
                final CompositeSubscription s = new CompositeSubscription();
                // if the child unsubscribes we unsubscribe our parent as well
                child.add(s);
    
                //capture the HystrixRequestContext upfront so that we can use it in the timeout thread later
                final HystrixRequestContext hystrixRequestContext = HystrixRequestContext.getContextForCurrentThread();
    
                TimerListener listener = new TimerListener() {
    
                    @Override
                    public void tick() {
                        // if we can go from NOT_EXECUTED to TIMED_OUT then we do the timeout codepath
                        // otherwise it means we lost a race and the run() execution completed or did not start
                        if (originalCommand.isCommandTimedOut.compareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.TIMED_OUT)) {
                            // report timeout failure
                            originalCommand.eventNotifier.markEvent(HystrixEventType.TIMEOUT, originalCommand.commandKey);
    
                            // shut down the original request
                            s.unsubscribe();
    
                            final HystrixContextRunnable timeoutRunnable = new HystrixContextRunnable(originalCommand.concurrencyStrategy, hystrixRequestContext, new Runnable() {
    
                                @Override
                                public void run() {
                                    child.onError(new HystrixTimeoutException());
                                }
                            });
    
    
                            timeoutRunnable.run();
                            //if it did not start, then we need to mark a command start for concurrency metrics, and then issue the timeout
                        }
                    }
    
                    @Override
                    public int getIntervalTimeInMilliseconds() {
                        return originalCommand.properties.executionTimeoutInMilliseconds().get();
                    }
                };
    
                final Reference<TimerListener> tl = HystrixTimer.getInstance().addTimerListener(listener);
    
                // set externally so execute/queue can see this
                originalCommand.timeoutTimer.set(tl);
    
                /**
                 * If this subscriber receives values it means the parent succeeded/completed
                 */
                Subscriber<R> parent = new Subscriber<R>() {
    
                    @Override
                    public void onCompleted() {
                        if (isNotTimedOut()) {
                            // stop timer and pass notification through
                            tl.clear();
                            child.onCompleted();
                        }
                    }
    
                    @Override
                    public void onError(Throwable e) {
                        if (isNotTimedOut()) {
                            // stop timer and pass notification through
                            tl.clear();
                            child.onError(e);
                        }
                    }
    
                    @Override
                    public void onNext(R v) {
                        if (isNotTimedOut()) {
                            child.onNext(v);
                        }
                    }
    
                    private boolean isNotTimedOut() {
                        // if already marked COMPLETED (by onNext) or succeeds in setting to COMPLETED
                        return originalCommand.isCommandTimedOut.get() == TimedOutStatus.COMPLETED ||
                                originalCommand.isCommandTimedOut.compareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.COMPLETED);
                    }
    
                };
    
                // if s is unsubscribed we want to unsubscribe the parent
                s.add(parent);
    
                return parent;
            }
    
        }

    executeCommandWithSpecifiedIsolation方法

      真正执行命令的方法,有两种方式执行,一种是使用线程池执行,一种是使用当前线程执行。

    private Observable<R> executeCommandWithSpecifiedIsolation(final AbstractCommand<R> _cmd) {
            if (properties.executionIsolationStrategy().get() == ExecutionIsolationStrategy.THREAD) {
                //使用线程池执行
                return Observable.defer(new Func0<Observable<R>>() {
                    @Override
                    public Observable<R> call() {
                        executionResult = executionResult.setExecutionOccurred();
                        if (!commandState.compareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.USER_CODE_EXECUTED)) {
                            return Observable.error(new IllegalStateException("execution attempted while in state : " + commandState.get().name()));
                        }
    
                        metrics.markCommandStart(commandKey, threadPoolKey, ExecutionIsolationStrategy.THREAD);//调用命令开始执行metrics
    
                        if (isCommandTimedOut.get() == TimedOutStatus.TIMED_OUT) {
                            // the command timed out in the wrapping thread so we will return immediately
                            // and not increment any of the counters below or other such logic
                            return Observable.error(new RuntimeException("timed out before executing run()"));
                        }
                        if (threadState.compareAndSet(ThreadState.NOT_USING_THREAD, ThreadState.STARTED)) {//修改threadState状态
                            //we have not been unsubscribed, so should proceed
                            HystrixCounters.incrementGlobalConcurrentThreads();
                            threadPool.markThreadExecution(); //调用线程池开始方法metrics
                            // store the command that is being run
                            endCurrentThreadExecutingCommand = Hystrix.startCurrentThreadExecutingCommand(getCommandKey());
                            executionResult = executionResult.setExecutedInThread();//设置在线程池中执行
                            try {
                                executionHook.onThreadStart(_cmd);//调用hook的onThread
                                executionHook.onRunStart(_cmd);//调用hook的onRunStart
                                executionHook.onExecutionStart(_cmd);//调用hook的onExecutionStart
                                return getUserExecutionObservable(_cmd);
                            } catch (Throwable ex) {
                                return Observable.error(ex);
                            }
                        } else {
                            //command has already been unsubscribed, so return immediately
                            return Observable.empty();
                        }
                    }
                }).doOnTerminate(new Action0() {
                    @Override
                    public void call() {
                        if (threadState.compareAndSet(ThreadState.STARTED, ThreadState.TERMINAL)) {
                            handleThreadEnd(_cmd);
                        }
                        if (threadState.compareAndSet(ThreadState.NOT_USING_THREAD, ThreadState.TERMINAL)) {
                            //if it was never started and received terminal, then no need to clean up (I don't think this is possible)
                        }
                        //if it was unsubscribed, then other cleanup handled it
                    }
                }).doOnUnsubscribe(new Action0() {
                    @Override
                    public void call() {
                        if (threadState.compareAndSet(ThreadState.STARTED, ThreadState.UNSUBSCRIBED)) {
                            handleThreadEnd(_cmd);
                        }
                        if (threadState.compareAndSet(ThreadState.NOT_USING_THREAD, ThreadState.UNSUBSCRIBED)) {
                            //if it was never started and was cancelled, then no need to clean up
                        }
                        //if it was terminal, then other cleanup handled it
                    }
                }).subscribeOn(threadPool.getScheduler(new Func0<Boolean>() {//使用线程池执行
                    @Override
                    public Boolean call() {
                        return properties.executionIsolationThreadInterruptOnTimeout().get() && _cmd.isCommandTimedOut.get() == TimedOutStatus.TIMED_OUT;
                    }
                }));
            } else {
                return Observable.defer(new Func0<Observable<R>>() {
                    @Override
                    public Observable<R> call() {
                        executionResult = executionResult.setExecutionOccurred();
                        if (!commandState.compareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.USER_CODE_EXECUTED)) {
                            return Observable.error(new IllegalStateException("execution attempted while in state : " + commandState.get().name()));
                        }
                        metrics.markCommandStart(commandKey, threadPoolKey, ExecutionIsolationStrategy.SEMAPHORE);//调用命令开始执行metrics
                        // semaphore isolated
                        // store the command that is being run
                        endCurrentThreadExecutingCommand = Hystrix.startCurrentThreadExecutingCommand(getCommandKey());
                        try {
                            executionHook.onRunStart(_cmd);//调用hook的onRunStart
                            executionHook.onExecutionStart(_cmd);//调用hook的onExecutionStart
                            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);
                        }
                    }
                });
            }
        }

     

  • 相关阅读:
    sql server delete语句
    sql server 通配符
    sql server join联结
    windows下如何使用两个版本的nodejs
    PHP的Trait 特性
    PHP错误与异常处理try和catch
    laravel belongsTo()&hasOne()用法详解
    Laravel Model 的 fillable (白名单)与 guarded (黑名单)
    js原生,缓动动画封装
    js原生轮播图
  • 原文地址:https://www.cnblogs.com/zhangwanhua/p/7909935.html
Copyright © 2020-2023  润新知