springcloud五大组件之熔断器

本文介绍Spring Cloud中Hystrix熔断器的配置与使用方式,包括自动配置类、熔断器健康检查指标、WebFlux与Servlet两种环境下Hystrix的集成配置。同时探讨了HystrixCommand的执行逻辑、熔断机制及线程池资源获取等关键环节。
摘要由CSDN通过智能技术生成

springcloud五大组件之熔断器

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnClass({Hystrix.class, HealthIndicator.class, HealthContributorAutoConfiguration.class})
@AutoConfigureAfter({HealthContributorAutoConfiguration.class})
public class HystrixAutoConfiguration {
    public HystrixAutoConfiguration() {
    }

    @Bean
    @ConditionalOnEnabledHealthIndicator("hystrix")
    public HystrixHealthIndicator hystrixHealthIndicator() {
        return new HystrixHealthIndicator();
    }

    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnWebApplication(
        type = Type.REACTIVE
    )
    @ConditionalOnBean({HystrixCommandAspect.class})
    @ConditionalOnClass({DispatcherHandler.class})
    @EnableConfigurationProperties({HystrixProperties.class})
    protected static class HystrixWebfluxManagementContextConfiguration {
        protected HystrixWebfluxManagementContextConfiguration() {
        }

        @Bean
        @ConditionalOnAvailableEndpoint
        public HystrixWebfluxEndpoint hystrixWebfluxController() {
            Observable<String> serializedDashboardData = 							Q			   HystrixDashboardStream.getInstance().observe().concatMap((dashboardData) -> {
                return Observable.from(SerialHystrixDashboardData
                                       .toMultipleJsonStrings(dashboardData));
            });
            Publisher<String> publisher = 															RxReactiveStreams.toPublisher(serializedDashboardData);
            return new HystrixWebfluxEndpoint(publisher);
        }

        @Bean
        public HasFeatures hystrixStreamFeature() {
            return HasFeatures.namedFeature("Hystrix Stream Webflux", 									HystrixWebfluxEndpoint.class);
        }
    }

    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnWebApplication(
        type = Type.SERVLET
    )
    @ConditionalOnBean({HystrixCommandAspect.class})
    @ConditionalOnClass({HystrixMetricsStreamServlet.class})
    @EnableConfigurationProperties({HystrixProperties.class})
    protected static class HystrixServletAutoConfiguration {
        protected HystrixServletAutoConfiguration() {
        }

        @Bean
        @ConditionalOnAvailableEndpoint
        public HystrixStreamEndpoint hystrixStreamEndpoint(HystrixProperties properties) {
            return new HystrixStreamEndpoint(properties.getConfig());
        }

        @Bean
        public HasFeatures hystrixStreamFeature() {
            return HasFeatures.namedFeature("Hystrix Stream Servlet", 									HystrixMetricsStreamServlet.class);
        }
    }

    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnProperty(
        value = {"management.metrics.binders.hystrix.enabled"},
        matchIfMissing = true
    )
    @ConditionalOnClass({HystrixMetricsBinder.class})
    protected static class HystrixMetricsConfiguration {
        protected HystrixMetricsConfiguration() {
        }

        @Bean
        public HystrixMetricsBinder hystrixMetricsBinder() {
            return new HystrixMetricsBinder();
        }
    }
}
 @Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")
public Object methodsAnnotatedWithHystrixCommand(ProceedingJoinPoint joinPoint) throws 		Throwable {
        Method method = AopUtils.getMethodFromTarget(joinPoint);
        Validate.notNull(method, "failed to get method from joinPoint: %s", new Object[]			{joinPoint});
        if (method.isAnnotationPresent(HystrixCommand.class) && 									method.isAnnotationPresent(HystrixCollapser.class)) {
            throw new IllegalStateException("method cannot be annotated with HystrixCommand 				and HystrixCollapser annotations at the same time");
        } else {
            HystrixCommandAspect.MetaHolderFactory metaHolderFactory = 								 	(HystrixCommandAspect.MetaHolderFactory)META_HOLDER_FACTORY_MAP
              	 .get(HystrixCommandAspect.HystrixPointcutType.of(method));
            MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
            HystrixInvokable invokable = 															HystrixCommandFactory.getInstance().create(metaHolder);
            ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ? 					metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();

            try {
                Object result;
                if (!metaHolder.isObservable()) {
                    result = CommandExecutor.execute(invokable, executionType, metaHolder);
                } else {
                    result = this.executeObservable(invokable, executionType, metaHolder);
                }

                return result;
            } catch (HystrixBadRequestException var9) {
                throw var9.getCause();
            } catch (HystrixRuntimeException var10) {
                throw this.hystrixRuntimeExceptionToThrowable(metaHolder, var10);
            }
        }
    }
public MetaHolder create(ProceedingJoinPoint joinPoint) {
    Method method = AopUtils.getMethodFromTarget(joinPoint);
    Object obj = joinPoint.getTarget();
    Object[] args = joinPoint.getArgs();
    Object proxy = joinPoint.getThis();
    return this.create(proxy, method, obj, args, joinPoint);
}
public MetaHolder create(Object proxy, Method method, Object obj, Object[] args, 			ProceedingJoinPoint joinPoint) {
     HystrixCommand hystrixCommand = 														(HystrixCommand)method.getAnnotation(HystrixCommand.class);
         ExecutionType executionType = 															ExecutionType.getExecutionType(method.getReturnType());
     Builder builder = this.metaHolderBuilder(proxy, method, obj, args, joinPoint);
     if (EnvUtils.isCompileWeaving()) {
          builder.ajcMethod(HystrixCommandAspect.getAjcMethodFromTarget(joinPoint));
     }

     return 																				builder.defaultCommandKey(method.getName()).hystrixCommand(hystrixCommand)
		.observableExecutionMode(hystrixCommand.observableExecutionMode())
         .executionType(executionType).observable(ExecutionType.OBSERVABLE == 					executionType).build();
}
public HystrixInvokable create(MetaHolder metaHolder) {
    Object executable;
    if (metaHolder.isCollapserAnnotationPresent()) {
        executable = new CommandCollapser(metaHolder);
    } else if (metaHolder.isObservable()) {
        executable = new GenericObservableCommand(
          HystrixCommandBuilderFactory.getInstance().create(metaHolder));
    } else {
        executable = new GenericCommand(HystrixCommandBuilderFactory
                     .getInstance().create(metaHolder));
    }
    return (HystrixInvokable)executable;
}
public HystrixCommandBuilder create(MetaHolder metaHolder) {
    return this.create(metaHolder, Collections.emptyList());
}
public <ResponseType> HystrixCommandBuilder create(MetaHolder metaHolder, 					Collection<CollapsedRequest<ResponseType, Object>> collapsedRequests) {
    this.validateMetaHolder(metaHolder);
    return HystrixCommandBuilder.builder().setterBuilder(
       this.createGenericSetterBuilder(metaHolder)).commandActions(
       this.createCommandActions(metaHolder)).collapsedRequests(collapsedRequests)
      .cacheResultInvocationContext(CacheInvocationContextFactory
      .createCacheResultInvocationContext(metaHolder))
      .cacheRemoveInvocationContext(CacheInvocationContextFactory
      .createCacheRemoveInvocationContext(metaHolder))
      .ignoreExceptions(metaHolder.getCommandIgnoreExceptions())
      .executionType(metaHolder.getExecutionType()).build();
}
public GenericCommand(HystrixCommandBuilder builder) {
    super(builder);
}
protected AbstractHystrixCommand(HystrixCommandBuilder builder) {
    super(builder.getSetterBuilder().build());
    this.commandActions = builder.getCommandActions();
    this.collapsedRequests = builder.getCollapsedRequests();
    this.cacheResultInvocationContext = builder.getCacheResultInvocationContext();
    this.cacheRemoveInvocationContext = builder.getCacheRemoveInvocationContext();
    this.ignoreExceptions = builder.getIgnoreExceptions();
    this.executionType = builder.getExecutionType();
}
protected HystrixCommand(HystrixCommand.Setter setter) {
    this(setter.groupKey, setter.commandKey, setter.threadPoolKey, 								(HystrixCircuitBreaker)null, (HystrixThreadPool)null, 
         setter.commandPropertiesDefaults, setter.threadPoolPropertiesDefaults, 				(HystrixCommandMetrics)null, (TryableSemaphore)null, 
         (TryableSemaphore)null, (HystrixPropertiesStrategy)null, 								(HystrixCommandExecutionHook)null);
}
HystrixCommand(HystrixCommandGroupKey group, HystrixCommandKey key, HystrixThreadPoolKey 	 threadPoolKey, HystrixCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, 	com.netflix.hystrix.HystrixCommandProperties.Setter commandPropertiesDefaults, 			com.netflix.hystrix.HystrixThreadPoolProperties.Setter threadPoolPropertiesDefaults, 	 HystrixCommandMetrics metrics, TryableSemaphore fallbackSemaphore, TryableSemaphore 	 executionSemaphore, HystrixPropertiesStrategy propertiesStrategy, 						HystrixCommandExecutionHook executionHook) {
    super(group, key, threadPoolKey, circuitBreaker, threadPool, commandPropertiesDefaults, 		threadPoolPropertiesDefaults, metrics, fallbackSemaphore, executionSemaphore, 			propertiesStrategy, executionHook);
    this.executionThread = new AtomicReference();
    this.interruptOnFutureCancel = new AtomicBoolean(false);
}
protected AbstractCommand(HystrixCommandGroupKey group, HystrixCommandKey key, 				HystrixThreadPoolKey threadPoolKey, HystrixCircuitBreaker circuitBreaker
    , HystrixThreadPool threadPool, Setter commandPropertiesDefaults, 						com.netflix.hystrix.HystrixThreadPoolProperties.Setter 
    threadPoolPropertiesDefaults, HystrixCommandMetrics metrics, 							AbstractCommand.TryableSemaphore fallbackSemaphore, 
    AbstractCommand.TryableSemaphore executionSemaphore, 
    HystrixPropertiesStrategy propertiesStrategy, 
    HystrixCommandExecutionHook executionHook) {
    this.commandState = new AtomicReference(AbstractCommand.CommandState.NOT_STARTED);
    this.threadState = new AtomicReference(AbstractCommand.ThreadState.NOT_USING_THREAD);
    this.executionResult = ExecutionResult.EMPTY;
    this.isResponseFromCache = false;
    this.commandStartTimestamp = -1L;
    this.isCommandTimedOut = new 															AtomicReference(AbstractCommand.TimedOutStatus.NOT_EXECUTED);
    this.commandGroup = initGroupKey(group);
    this.commandKey = initCommandKey(key, this.getClass());
    this.properties = initCommandProperties(this.commandKey, propertiesStrategy, 				commandPropertiesDefaults);
    this.threadPoolKey = initThreadPoolKey(threadPoolKey, this.commandGroup, 					(String)this.properties.executionIsolationThreadPoolKeyOverride().get());
    this.metrics = initMetrics(metrics, this.commandGroup, this.threadPoolKey, 					this.commandKey, this.properties);
    this.circuitBreaker = 																    initCircuitBreaker((Boolean)this.properties.circuitBreakerEnabled().get(),
        circuitBreaker, this.commandGroup, this.commandKey, this.properties, this.metrics);
    this.threadPool = initThreadPool(threadPool, this.threadPoolKey, 							threadPoolPropertiesDefaults);
    this.eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
    this.concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
    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((Boolean)this.properties.requestLogEnabled().get(), 						this.concurrencyStrategy);
    this.fallbackSemaphoreOverride = fallbackSemaphore;
    this.executionSemaphoreOverride = executionSemaphore;
}
private static HystrixCommandMetrics initMetrics(HystrixCommandMetrics fromConstructor, 	HystrixCommandGroupKey groupKey, HystrixThreadPoolKey threadPoolKey, HystrixCommandKey 	   commandKey, HystrixCommandProperties properties) {
    return fromConstructor == null ? HystrixCommandMetrics.getInstance(commandKey, 				groupKey, threadPoolKey, properties) : fromConstructor;
}
public static HystrixCommandMetrics getInstance(HystrixCommandKey key, 						HystrixCommandGroupKey commandGroup, HystrixThreadPoolKey threadPoolKey, 				HystrixCommandProperties properties) {
    HystrixCommandMetrics commandMetrics = (HystrixCommandMetrics)metrics.get(key.name());
    if (commandMetrics != null) {
        return commandMetrics;
    } else {
        Class var5 = HystrixCommandMetrics.class;
        synchronized(HystrixCommandMetrics.class) {
            HystrixCommandMetrics existingMetrics = 										       (HystrixCommandMetrics)metrics.get(key.name());
            if (existingMetrics != null) {
                return existingMetrics;
            } else {
                HystrixThreadPoolKey nonNullThreadPoolKey;
                if (threadPoolKey == null) {
                    nonNullThreadPoolKey = Factory.asKey(commandGroup.name());
                } else {
                    nonNullThreadPoolKey = threadPoolKey;
                }

                HystrixCommandMetrics newCommandMetrics = new HystrixCommandMetrics(key, 					commandGroup, nonNullThreadPoolKey, properties, 									   HystrixPlugins.getInstance().getEventNotifier());
                metrics.putIfAbsent(key.name(), newCommandMetrics);
                return newCommandMetrics;
            }
        }
    }
}
HystrixCommandMetrics(HystrixCommandKey key, HystrixCommandGroupKey commandGroup, 			HystrixThreadPoolKey threadPoolKey, HystrixCommandProperties properties, 				HystrixEventNotifier eventNotifier) {
    super((HystrixRollingNumber)null);
    this.key = key;
    this.group = commandGroup;
    this.threadPoolKey = threadPoolKey;
    this.properties = properties;
    this.healthCountsStream = HealthCountsStream.getInstance(key, properties);
    this.rollingCommandEventCounterStream = 												RollingCommandEventCounterStream.getInstance(key, properties);
    this.cumulativeCommandEventCounterStream = 												CumulativeCommandEventCounterStream.getInstance(key, properties);
    this.rollingCommandLatencyDistributionStream = 											RollingCommandLatencyDistributionStream.getInstance(key, properties);
    this.rollingCommandUserLatencyDistributionStream = 											RollingCommandUserLatencyDistributionStream.getInstance(key, properties);
    this.rollingCommandMaxConcurrencyStream = 												RollingCommandMaxConcurrencyStream.getInstance(key, properties);
}
public static HealthCountsStream getInstance(HystrixCommandKey commandKey, 					HystrixCommandProperties properties) {
    int healthCountBucketSizeInMs = 														(Integer)properties.metricsHealthSnapshotIntervalInMilliseconds().get();
    if (healthCountBucketSizeInMs == 0) {
        throw new RuntimeException("You have set the bucket size to 0ms.  Please set a 			positive number, so that the metric stream can be properly consumed");
    } else {
        int numHealthCountBuckets = 															(Integer)properties.metricsRollingStatisticalWindowInMilliseconds().get() / 			healthCountBucketSizeInMs;
        return getInstance(commandKey, numHealthCountBuckets, healthCountBucketSizeInMs);
    }
}
public static HealthCountsStream getInstance(HystrixCommandKey commandKey, int numBuckets,     int bucketSizeInMs) {
    HealthCountsStream initialStream = (HealthCountsStream)streams.get(commandKey.name());
    if (initialStream != null) {
        return initialStream;
    } else {
        Class var5 = HealthCountsStream.class;
        HealthCountsStream healthStream;
        synchronized(HealthCountsStream.class) {
            HealthCountsStream existingStream = 											       (HealthCountsStream)streams.get(commandKey.name());
            if (existingStream == null) {
                HealthCountsStream newStream = new HealthCountsStream(commandKey, 					   numBuckets, bucketSizeInMs, HystrixCommandMetrics.appendEventToBucket);
                streams.putIfAbsent(commandKey.name(), newStream);
                healthStream = newStream;
            } else {
                healthStream = existingStream;
            }
        }

        healthStream.startCachingStreamValuesIfUnstarted();
        return healthStream;
    }
}
private HealthCountsStream(HystrixCommandKey commandKey, int numBuckets, int 				bucketSizeInMs, Func2<long[], HystrixCommandCompletion, long[]> 						reduceCommandCompletion) {
    super(HystrixCommandCompletionStream.getInstance(commandKey), numBuckets, 					bucketSizeInMs, reduceCommandCompletion, healthCheckAccumulator);
}
public static HystrixCommandCompletionStream getInstance(HystrixCommandKey commandKey) {
    HystrixCommandCompletionStream initialStream = (HystrixCommandCompletionStream)streams.get(commandKey.name());
    if (initialStream != null) {
        return initialStream;
    } else {
        Class var2 = HystrixCommandCompletionStream.class;
        synchronized(HystrixCommandCompletionStream.class) {
            HystrixCommandCompletionStream existingStream = (HystrixCommandCompletionStream)streams.get(commandKey.name());
            if (existingStream == null) {
                HystrixCommandCompletionStream newStream = new HystrixCommandCompletionStream(commandKey);
                streams.putIfAbsent(commandKey.name(), newStream);
                return newStream;
            } else {
                return existingStream;
            }
        }
    }
}
HystrixCommandCompletionStream(HystrixCommandKey commandKey) {
    this.commandKey = commandKey;
    this.writeOnlySubject = new SerializedSubject(PublishSubject.create());
    this.readOnlyStream = this.writeOnlySubject.share();
}
public static HystrixCommandCompletionStream getInstance(HystrixCommandKey commandKey) {
    HystrixCommandCompletionStream initialStream = 										(HystrixCommandCompletionStream)streams.get(commandKey.name());
    if (initialStream != null) {
        return initialStream;
    } else {
        Class var2 = HystrixCommandCompletionStream.class;
        synchronized(HystrixCommandCompletionStream.class) {
            HystrixCommandCompletionStream existingStream = 									       (HystrixCommandCompletionStream)streams.get(commandKey.name());
            if (existingStream == null) {
                HystrixCommandCompletionStream newStream = new 										       HystrixCommandCompletionStream(commandKey);
                streams.putIfAbsent(commandKey.name(), newStream);
                return newStream;
            } else {
                return existingStream;
            }
        }
    }
}
HystrixCommandCompletionStream(HystrixCommandKey commandKey) {
    this.commandKey = commandKey;
    this.writeOnlySubject = new SerializedSubject(PublishSubject.create());
    this.readOnlyStream = this.writeOnlySubject.share();
}
protected BucketedRollingCounterStream(HystrixEventStream<Event> stream, final int 			numBuckets, int bucketSizeInMs, Func2<Bucket, Event, Bucket> appendRawEventToBucket, 	 final Func2<Output, Bucket, Output> reduceBucket) {
    super(stream, numBuckets, bucketSizeInMs, appendRawEventToBucket);
    Func1<Observable<Bucket>, Observable<Output>> reduceWindowToSummary = new 					Func1<Observable<Bucket>, Observable<Output>>() {
          public Observable<Output> call(Observable<Bucket> window) {
              return window.scan(BucketedRollingCounterStream.this.getEmptyOutputValue(), 					reduceBucket).skip(numBuckets);
          }
	};
    this.sourceStream = this.bucketedStream.window(numBuckets, 									1).flatMap(reduceWindowToSummary).doOnSubscribe(new Action0() {
        public void call() {
            BucketedRollingCounterStream.this.isSourceCurrentlySubscribed.set(true);
        }
    }).doOnUnsubscribe(new Action0() {
        public void call() {
            BucketedRollingCounterStream.this.isSourceCurrentlySubscribed.set(false);
        }
    }).share().onBackpressureDrop();
}
protected BucketedCounterStream(final HystrixEventStream<Event> inputEventStream, int 		numBuckets, final int bucketSizeInMs, final Func2<Bucket, Event, Bucket> 				appendRawEventToBucket) {
    this.numBuckets = numBuckets;
    this.reduceBucketToSummary = new Func1<Observable<Event>, Observable<Bucket>>() {
        public Observable<Bucket> call(Observable<Event> eventBucket) {
            return eventBucket.reduce(BucketedCounterStream.this.getEmptyBucketSummary(), 					appendRawEventToBucket);
        }
    };
    final List<Bucket> emptyEventCountsToStart = new ArrayList();

    for(int i = 0; i < numBuckets; ++i) {
        emptyEventCountsToStart.add(this.getEmptyBucketSummary());
    }

    this.bucketedStream = Observable.defer(new Func0<Observable<Bucket>>() {
        public Observable<Bucket> call() {
            return inputEventStream.observe().window((long)bucketSizeInMs, 								TimeUnit.MILLISECONDS).flatMap(BucketedCounterStream
                  .this.reduceBucketToSummary).startWith(emptyEventCountsToStart);
        }
    });
}
public static Object execute(HystrixInvokable invokable, ExecutionType executionType, MetaHolder metaHolder) throws RuntimeException {
    Validate.notNull(invokable);
    Validate.notNull(metaHolder);
    switch(executionType) {
    case SYNCHRONOUS:
        return castToExecutable(invokable, executionType).execute();
    case ASYNCHRONOUS:
        HystrixExecutable executable = castToExecutable(invokable, executionType);
        if (metaHolder.hasFallbackMethodCommand() && ExecutionType.ASYNCHRONOUS == metaHolder.getFallbackExecutionType()) {
            return new FutureDecorator(executable.queue());
        }

        return executable.queue();
    case OBSERVABLE:
        HystrixObservable observable = castToObservable(invokable);
        return ObservableExecutionMode.EAGER == metaHolder.getObservableExecutionMode() ? observable.observe() : observable.toObservable();
    default:
        throw new RuntimeException("unsupported execution type: " + executionType);
    }
}
public R execute() {
    try {
        return this.queue().get();
    } catch (Exception var2) {
        throw Exceptions.sneakyThrow(this.decomposeException(var2));
    }
}
public Future<R> queue() {
    final Future<R> delegate = this.toObservable().toBlocking().toFuture();
    Future<R> f = new Future<R>() {
        public boolean cancel(boolean mayInterruptIfRunning) {
            if (delegate.isCancelled()) {
                return false;
            } else {
                if ((Boolean)HystrixCommand.this.getProperties().executionIsolationThreadInterruptOnFutureCancel().get()) {
                    HystrixCommand.this.interruptOnFutureCancel.compareAndSet(false, mayInterruptIfRunning);
                }

                boolean res = delegate.cancel(HystrixCommand.this.interruptOnFutureCancel.get());
                if (!HystrixCommand.this.isExecutionComplete() && HystrixCommand.this.interruptOnFutureCancel.get()) {
                    Thread t = (Thread)HystrixCommand.this.executionThread.get();
                    if (t != null && !t.equals(Thread.currentThread())) {
                        t.interrupt();
                    }
                }

                return res;
            }
        }

        public boolean isCancelled() {
            return delegate.isCancelled();
        }

        public boolean isDone() {
            return delegate.isDone();
        }

        public R get() throws InterruptedException, ExecutionException {
            return delegate.get();
        }

        public R get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
            return delegate.get(timeout, unit);
        }
    };
    if (f.isDone()) {
        try {
            f.get();
            return f;
        } catch (Exception var6) {
            Throwable t = this.decomposeException(var6);
            if (t instanceof HystrixBadRequestException) {
                return f;
            } else if (t instanceof HystrixRuntimeException) {
                HystrixRuntimeException hre = (HystrixRuntimeException)t;
                switch(hre.getFailureType()) {
                case COMMAND_EXCEPTION:
                case TIMEOUT:
                    return f;
                default:
                    throw hre;
                }
            } else {
                throw Exceptions.sneakyThrow(t);
            }
        }
    } else {
        return f;
    }
}
public Observable<R> toObservable() {
    final Action0 terminateCommandCleanup = new Action0() {
        public void call() {
            if (AbstractCommand.this.commandState.compareAndSet(AbstractCommand.CommandState.OBSERVABLE_CHAIN_CREATED, AbstractCommand.CommandState.TERMINAL)) {
                AbstractCommand.this.handleCommandEnd(false);
            } else if (AbstractCommand.this.commandState.compareAndSet(AbstractCommand.CommandState.USER_CODE_EXECUTED, AbstractCommand.CommandState.TERMINAL)) {
                AbstractCommand.this.handleCommandEnd(true);
            }

        }
    };
    final Action0 unsubscribeCommandCleanup = new Action0() {
        public void call() {
            if (AbstractCommand.this.commandState.compareAndSet(AbstractCommand.CommandState.OBSERVABLE_CHAIN_CREATED, AbstractCommand.CommandState.UNSUBSCRIBED)) {
                if (!AbstractCommand.this.executionResult.containsTerminalEvent()) {
                    AbstractCommand.this.eventNotifier.markEvent(HystrixEventType.CANCELLED, AbstractCommand.this.commandKey);

                    try {
                        AbstractCommand.this.executionHook.onUnsubscribe(AbstractCommand.this);
                    } catch (Throwable var3) {
                        AbstractCommand.logger.warn("Error calling HystrixCommandExecutionHook.onUnsubscribe", var3);
                    }

                    AbstractCommand.this.executionResultAtTimeOfCancellation = AbstractCommand.this.executionResult.addEvent((int)(System.currentTimeMillis() - AbstractCommand.this.commandStartTimestamp), HystrixEventType.CANCELLED);
                }

                AbstractCommand.this.handleCommandEnd(false);
            } else if (AbstractCommand.this.commandState.compareAndSet(AbstractCommand.CommandState.USER_CODE_EXECUTED, AbstractCommand.CommandState.UNSUBSCRIBED)) {
                if (!AbstractCommand.this.executionResult.containsTerminalEvent()) {
                    AbstractCommand.this.eventNotifier.markEvent(HystrixEventType.CANCELLED, AbstractCommand.this.commandKey);

                    try {
                        AbstractCommand.this.executionHook.onUnsubscribe(AbstractCommand.this);
                    } catch (Throwable var2) {
                        AbstractCommand.logger.warn("Error calling HystrixCommandExecutionHook.onUnsubscribe", var2);
                    }

                    AbstractCommand.this.executionResultAtTimeOfCancellation = AbstractCommand.this.executionResult.addEvent((int)(System.currentTimeMillis() - AbstractCommand.this.commandStartTimestamp), HystrixEventType.CANCELLED);
                }

                AbstractCommand.this.handleCommandEnd(true);
            }

        }
    };
    final Func0<Observable<R>> applyHystrixSemantics = new Func0<Observable<R>>() {
        public Observable<R> call() {
            return ((AbstractCommand.CommandState)AbstractCommand.this.commandState.get()).equals(AbstractCommand.CommandState.UNSUBSCRIBED) ? Observable.never() : AbstractCommand.this.applyHystrixSemantics(AbstractCommand.this);
        }
    };
    final Func1<R, R> wrapWithAllOnNextHooks = new Func1<R, R>() {
        public R call(R r) {
            Object afterFirstApplication = r;

            try {
                afterFirstApplication = AbstractCommand.this.executionHook.onComplete(AbstractCommand.this, r);
            } catch (Throwable var5) {
                AbstractCommand.logger.warn("Error calling HystrixCommandExecutionHook.onComplete", var5);
            }

            try {
                return AbstractCommand.this.executionHook.onEmit(AbstractCommand.this, afterFirstApplication);
            } catch (Throwable var4) {
                AbstractCommand.logger.warn("Error calling HystrixCommandExecutionHook.onEmit", var4);
                return afterFirstApplication;
            }
        }
    };
    final Action0 fireOnCompletedHook = new Action0() {
        public void call() {
            try {
                AbstractCommand.this.executionHook.onSuccess(AbstractCommand.this);
            } catch (Throwable var2) {
                AbstractCommand.logger.warn("Error calling HystrixCommandExecutionHook.onSuccess", var2);
            }

        }
    };
    return Observable.defer(new Func0<Observable<R>>() {
        public Observable<R> call() {
            if (!AbstractCommand.this.commandState.compareAndSet(AbstractCommand.CommandState.NOT_STARTED, AbstractCommand.CommandState.OBSERVABLE_CHAIN_CREATED)) {
                IllegalStateException ex = new IllegalStateException("This instance can only be executed once. Please instantiate a new instance.");
                throw new HystrixRuntimeException(FailureType.BAD_REQUEST_EXCEPTION, AbstractCommand.this.getClass(), AbstractCommand.this.getLogMessagePrefix() + " command executed multiple times - this is not permitted.", ex, (Throwable)null);
            } else {
                AbstractCommand.this.commandStartTimestamp = System.currentTimeMillis();
                if ((Boolean)AbstractCommand.this.properties.requestLogEnabled().get() && AbstractCommand.this.currentRequestLog != null) {
                    AbstractCommand.this.currentRequestLog.addExecutedCommand(AbstractCommand.this);
                }

                boolean requestCacheEnabled = AbstractCommand.this.isRequestCachingEnabled();
                String cacheKey = AbstractCommand.this.getCacheKey();
                if (requestCacheEnabled) {
                    HystrixCommandResponseFromCache<R> fromCachex = (HystrixCommandResponseFromCache)AbstractCommand.this.requestCache.get(cacheKey);
                    if (fromCachex != null) {
                        AbstractCommand.this.isResponseFromCache = true;
                        return AbstractCommand.this.handleRequestCacheHitAndEmitValues(fromCachex, AbstractCommand.this);
                    }
                }

                Observable<R> hystrixObservable = Observable.defer(applyHystrixSemantics).map(wrapWithAllOnNextHooks);
                Observable afterCache;
                if (requestCacheEnabled && cacheKey != null) {
                    HystrixCachedObservable<R> toCache = HystrixCachedObservable.from(hystrixObservable, AbstractCommand.this);
                    HystrixCommandResponseFromCache<R> fromCache = (HystrixCommandResponseFromCache)AbstractCommand.this.requestCache.putIfAbsent(cacheKey, toCache);
                    if (fromCache != null) {
                        toCache.unsubscribe();
                        AbstractCommand.this.isResponseFromCache = true;
                        return AbstractCommand.this.handleRequestCacheHitAndEmitValues(fromCache, AbstractCommand.this);
                    }

                    afterCache = toCache.toObservable();
                } else {
                    afterCache = hystrixObservable;
                }

                return afterCache.doOnTerminate(terminateCommandCleanup).doOnUnsubscribe(unsubscribeCommandCleanup).doOnCompleted(fireOnCompletedHook);
            }
        }
    });
}
private Observable<R> applyHystrixSemantics(AbstractCommand<R> _cmd) {
    this.executionHook.onStart(_cmd);
    if (this.circuitBreaker.allowRequest()) {
        final AbstractCommand.TryableSemaphore executionSemaphore = this.getExecutionSemaphore();
        final AtomicBoolean semaphoreHasBeenReleased = new AtomicBoolean(false);
        Action0 singleSemaphoreRelease = new Action0() {
            public void call() {
                if (semaphoreHasBeenReleased.compareAndSet(false, true)) {
                    executionSemaphore.release();
                }

            }
        };
        Action1<Throwable> markExceptionThrown = new Action1<Throwable>() {
            public void call(Throwable t) {
                AbstractCommand.this.eventNotifier.markEvent(HystrixEventType.EXCEPTION_THROWN, AbstractCommand.this.commandKey);
            }
        };
        if (executionSemaphore.tryAcquire()) {
            try {
                this.executionResult = this.executionResult.setInvocationStartTime(System.currentTimeMillis());
                return this.executeCommandAndObserve(_cmd).doOnError(markExceptionThrown).doOnTerminate(singleSemaphoreRelease).doOnUnsubscribe(singleSemaphoreRelease);
            } catch (RuntimeException var7) {
                return Observable.error(var7);
            }
        } else {
            return this.handleSemaphoreRejectionViaFallback();
        }
    } else {
        return this.handleShortCircuitViaFallback();
    }
}
public boolean allowRequest() {
    if ((Boolean)this.properties.circuitBreakerForceOpen().get()) {
        return false;
    } else if ((Boolean)this.properties.circuitBreakerForceClosed().get()) {
        this.isOpen();
        return true;
    } else {
        return !this.isOpen() || this.allowSingleTest();
    }
}
public boolean isOpen() {
    if (this.circuitOpen.get()) {
        return true;
    } else {
        HealthCounts health = this.metrics.getHealthCounts();
        if (health.getTotalRequests() < (long)(Integer)this.properties.circuitBreakerRequestVolumeThreshold().get()) {
            return false;
        } else if (health.getErrorPercentage() < (Integer)this.properties.circuitBreakerErrorThresholdPercentage().get()) {
            return false;
        } else if (this.circuitOpen.compareAndSet(false, true)) {
            this.circuitOpenedOrLastTestedTime.set(System.currentTimeMillis());
            return true;
        } else {
            return true;
        }
    }
}
public boolean tryAcquire() {
    int currentCount = this.count.incrementAndGet();
    if (currentCount > (Integer)this.numberOfPermits.get()) {
        this.count.decrementAndGet();
        return false;
    } else {
        return true;
    }
}
public boolean tryAcquire() {
    return true;
}
private Observable<R> executeCommandAndObserve(AbstractCommand<R> _cmd) {
    final HystrixRequestContext currentRequestContext = HystrixRequestContext.getContextForCurrentThread();
    Action1<R> markEmits = new Action1<R>() {
        public void call(R r) {
            if (AbstractCommand.this.shouldOutputOnNextEvents()) {
                AbstractCommand.this.executionResult = 												   AbstractCommand.this.executionResult.addEvent(HystrixEventType.EMIT);
                AbstractCommand.this.eventNotifier.markEvent(HystrixEventType.EMIT, 					AbstractCommand.this.commandKey);
            }

            if (AbstractCommand.this.commandIsScalar()) {
                long latency = System.currentTimeMillis() - 												AbstractCommand.this.executionResult.getStartTimestamp();
                AbstractCommand.this.eventNotifier.markCommandExecution(
                AbstractCommand.this.getCommandKey(),											   (ExecutionIsolationStrategy)AbstractCommand.this.properties
                .executionIsolationStrategy().get(), (int)latency, 										AbstractCommand.this.executionResult.getOrderedList());
                AbstractCommand.this.eventNotifier.markEvent(HystrixEventType.SUCCESS, 				   AbstractCommand.this.commandKey);
                AbstractCommand.this.executionResult = 												   AbstractCommand.this.executionResult.addEvent((int)latency, 
                HystrixEventType.SUCCESS);
                AbstractCommand.this.circuitBreaker.markSuccess();
            }

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

        }
    };
   Func1<Throwable, Observable<R>> handleFallback = new Func1<Throwable, Observable<R>>(){
        public Observable<R> call(Throwable t) {
            Exception e = AbstractCommand.this.getExceptionFromThrowable(t);
            AbstractCommand.this.executionResult = 													AbstractCommand.this.executionResult.setExecutionException(e);
            if (e instanceof RejectedExecutionException) {
                return AbstractCommand.this.handleThreadPoolRejectionViaFallback(e);
            } else if (t instanceof HystrixTimeoutException) {
                return AbstractCommand.this.handleTimeoutViaFallback();
            } else if (t instanceof HystrixBadRequestException) {
                return AbstractCommand.this.handleBadRequestByEmittingError(e);
            } else if (e instanceof HystrixBadRequestException) {
                AbstractCommand.this.eventNotifier.markEvent(HystrixEventType.BAD_REQUEST, 				  AbstractCommand.this.commandKey);
                return Observable.error(e);
            } else {
                return AbstractCommand.this.handleFailureViaFallback(e);
            }
        }
    };
    Action1<Notification<? super R>> setRequestContext = new Action1<Notification<? super 		R>>() {
        public void call(Notification<? super R> rNotification) {
            AbstractCommand.setRequestContextIfNeeded(currentRequestContext);
        }
    };
    Observable execution;
    if ((Boolean)this.properties.executionTimeoutEnabled().get()) {
        execution = this.executeCommandWithSpecifiedIsolation(_cmd).lift(new 					AbstractCommand.HystrixObservableTimeoutOperator(_cmd));
    } else {
        execution = this.executeCommandWithSpecifiedIsolation(_cmd);
    }

    return execution.doOnNext(markEmits).doOnCompleted(markOnCompleted)
      .onErrorResumeNext(handleFallback).doOnEach(setRequestContext);
}
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);

                    if (isCommandTimedOut.get() == TimedOutStatus.TIMED_OUT) {
						return Observable.error(new RuntimeException("timed out before 							executing run()"));
                    }
                    if (threadState.compareAndSet(ThreadState.NOT_USING_THREAD, 							ThreadState.STARTED)) {
                        HystrixCounters.incrementGlobalConcurrentThreads();
                        threadPool.markThreadExecution();                        							  endCurrentThreadExecutingCommand = 												  Hystrix.startCurrentThreadExecutingCommand(getCommandKey());
                        executionResult = executionResult.setExecutedInThread();
                        try {
                            executionHook.onThreadStart(_cmd);
                            executionHook.onRunStart(_cmd);
                            executionHook.onExecutionStart(_cmd);
                            return getUserExecutionObservable(_cmd);
                        } catch (Throwable ex) {
                            return Observable.error(ex);
                        }
                    } else {
                        return Observable.error(new RuntimeException("unsubscribed before 							executing run()"));
                    }
                }
            }).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)) {
                    }
                }
            }).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)) {
                       
                    }
                }
            }).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);
                    endCurrentThreadExecutingCommand = 															Hystrix.startCurrentThreadExecutingCommand(getCommandKey());
                    try {
                        executionHook.onRunStart(_cmd);
                        executionHook.onExecutionStart(_cmd);
                        return getUserExecutionObservable(_cmd);
                    } catch (Throwable ex) {
                        return Observable.error(ex);
                    }
                }
            });
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值