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