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);
- }
- }
- });
- }
- }
hystrix源码之AbstractCommand的更多相关文章
- Hystrix源码解析
1. Hystrix源码解析 1.1. @HystrixCommand原理 直接通过Aspect切面来做的 1.2. feign hystrix原理 它的本质原理就是对HystrixCommand的动 ...
- 【一起学源码-微服务】Hystrix 源码一:Hystrix基础原理与Demo搭建
说明 原创不易,如若转载 请标明来源! 欢迎关注本人微信公众号:壹枝花算不算浪漫 更多内容也可查看本人博客:一枝花算不算浪漫 前言 前情回顾 上一个系列文章讲解了Feign的源码,主要是Feign动态 ...
- hystrix源码之概述
概述 hystrix核心原理是通过代理执行用户命令,记录命令执行的metrics信息,通过这些metrics信息进行降级和熔断. 源码结构包括一下几个部分: 熔断器 熔断器就是hystrix用来判断调 ...
- 【一起学源码-微服务】Hystrix 源码二:Hystrix核心流程:Hystix非降级逻辑流程梳理
说明 原创不易,如若转载 请标明来源! 欢迎关注本人微信公众号:壹枝花算不算浪漫 更多内容也可查看本人博客:一枝花算不算浪漫 前言 前情回顾 上一讲我们讲了配置了feign.hystrix.enabl ...
- 【一起学源码-微服务】Hystrix 源码三:Hystrix核心流程:Hystix降级、熔断等原理剖析
说明 原创不易,如若转载 请标明来源! 欢迎关注本人微信公众号:壹枝花算不算浪漫 更多内容也可查看本人博客:一枝花算不算浪漫 前言 前情回顾 上一讲我们讲解了Hystrix在配合feign的过程中,一 ...
- hystrix 源码分析以及属性的配置
一.feign与hystix结合 1.1测试环境搭建 架构如图: 非常简单,就是Order服务通过feign调用product服务的一个获取商品信息的一个接口: package com.yang.xi ...
- Feign整合Ribbon和Hystrix源码解析
在上篇文章Feign自动装配中,我们提到了Feign的自动装配的原理,以及Feign整合Ribbon和Hystrix的核心在类FeignClientFactoryBean中,那么本篇文章就来揭开这个类 ...
- hystrix源码小贴士之之hystrix-metrics-event-stream
hystrix-metrics-event-stream主要提供了一些servlet,可以让用户通过http请求获取metrics信息. HystrixSampleSseServlet 继承了Http ...
- hystrix源码小贴士之调用异常处理
executeCommandAndObserve方法处理onerror异常. return execution.doOnNext(markEmits) .doOnCompleted(markOnCom ...
随机推荐
- Markdown实验样例
一级标题 二级标题 三级标题 重新开始一个段落 这是新的段落 斜体文本 粗体文本 粗斜体文本 下面是分隔线 删除线 下划线 脚注[1] 无序列表 第一项 嵌套元素1 嵌套元素2 第二项 嵌套元素1 嵌 ...
- python 05 列表 元组 (序列)
循环(loop),指的是在满足条件的情况下,重复执行同一段代码.比如,while语句. [ 循环则技能对应集合,列表,数组等,也能对执行代码进行操作.] 迭代(iterate),指的是按照某种顺序逐个 ...
- JavaScript学习系列博客_26_JavaScript 数组的一些方法
数组的一些方法 - push() - 用来向数组的末尾添加一个或多个元素,并返回数组新的长度 - 语法:数组.push(元素1,元素2,元素N) - pop() - 用来删除数组的最后一个元素,并返回 ...
- ucore学习
1.启动操作系统的bootloader,用于了解操作系统启动前的状态和要做的准备工作,了解运行操作系统的硬件支持,操作系统如何加载到内存中,理解两类中断--"外设中断"," ...
- linux 使用 FIO 测试磁盘的iops
原文链接:https://www.iteye.com/blog/elf8848-2168876 一,FIO安装wget http://brick.kernel.dk/snaps/fio-2.2.5.t ...
- 文华财经赢顺外盘期货行情数据API接口开放代码
文华财经赢顺外盘期货行情数据API接口开放代码 怎么才能获取到外盘期货行情数据API接口呢?不少朋友就会考虑到文华财经行情API接口,本身文华财经就是一个软件提供商,提供行情API接口也 ...
- Git仓库由HTTPS切换成ssh秘钥连接
Git关联远程仓库可以使用https协议或者ssh协议. [特点/优缺点] ssh: 一般使用22端口: 通过先在本地生成SSH密钥对再把公钥上传到服务器: 速度较慢点 https: 一般使用443端 ...
- 使用Seq搭建免费的日志服务
Seq简介 Seq是老外开发的一个针对.NET平台非常友好的日志服务.支持容器部署,提供一个单用户免费的开发版本. 官网:https://datalust.co/seq 使用文档:https://do ...
- Kubernetes Operator基础入门
本文转自Rancher Labs 你是否曾经想过SRE团队是如何有效地成功管理复杂的应用?在Kubernetes生态系统中,Kubernetes Operator可以给你答案.在本文中,我们将研究Op ...
- React的几种组件
一.函数组件 该函数在React中是一个有效的组件,可以接收唯一带有数据的props(代表属性)对象,并返回一个React元素.函数式组件要特别注意,组件名称首字母一定要大写.这种方式也成为无状态组件 ...