All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.hystrix.Hystrix Maven / Gradle / Ivy

There is a newer version: 1.5.18
Show newest version
/**
 * Copyright 2015 Netflix, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.netflix.hystrix;

import java.util.NoSuchElementException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import com.netflix.hystrix.strategy.HystrixPlugins;
import com.netflix.hystrix.strategy.properties.HystrixPropertiesFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import rx.functions.Action0;

/**
 * Lifecycle management of Hystrix.
 */
public class Hystrix {

    private static final Logger logger = LoggerFactory.getLogger(Hystrix.class);

    /**
     * Reset state and release resources in use (such as thread-pools).
     * 

* NOTE: This can result in race conditions if HystrixCommands are concurrently being executed. *

*/ public static void reset() { // shutdown thread-pools HystrixThreadPool.Factory.shutdown(); _reset(); } /** * Reset state and release resources in use (such as threadpools) and wait for completion. *

* NOTE: This can result in race conditions if HystrixCommands are concurrently being executed. *

* * @param time * time to wait for thread-pools to shutdown * @param unit * {@link TimeUnit} for
time
to wait for thread-pools to shutdown */ public static void reset(long time, TimeUnit unit) { // shutdown thread-pools HystrixThreadPool.Factory.shutdown(time, unit); _reset(); } /** * Reset logic that doesn't have time/TimeUnit arguments. */ private static void _reset() { // clear metrics HystrixCommandMetrics.reset(); HystrixThreadPoolMetrics.reset(); HystrixCollapserMetrics.reset(); // clear collapsers HystrixCollapser.reset(); // clear circuit breakers HystrixCircuitBreaker.Factory.reset(); HystrixPlugins.reset(); HystrixPropertiesFactory.reset(); currentCommand.set(new ConcurrentStack()); } private static ThreadLocal> currentCommand = new ThreadLocal>() { @Override protected ConcurrentStack initialValue() { return new ConcurrentStack(); } }; /** * Allows a thread to query whether it's current point of execution is within the scope of a HystrixCommand. *

* When ExecutionIsolationStrategy is THREAD then this applies to the isolation (child/worker) thread not the calling thread. *

* When ExecutionIsolationStrategy is SEMAPHORE this applies to the calling thread. * * @return HystrixCommandKey of current command being executed or null if none. */ public static HystrixCommandKey getCurrentThreadExecutingCommand() { if (currentCommand == null) { // statics do "interesting" things across classloaders apparently so this can somehow be null ... return null; } return currentCommand.get().peek(); } /** * * @return Action0 to perform the same work as `endCurrentThreadExecutingCommand()` but can be done from any thread */ /* package */static Action0 startCurrentThreadExecutingCommand(HystrixCommandKey key) { final ConcurrentStack list = currentCommand.get(); try { list.push(key); } catch (Exception e) { logger.warn("Unable to record command starting", e); } return new Action0() { @Override public void call() { endCurrentThreadExecutingCommand(list); } }; } /* package */static void endCurrentThreadExecutingCommand() { endCurrentThreadExecutingCommand(currentCommand.get()); } private static void endCurrentThreadExecutingCommand(ConcurrentStack list) { try { if (!list.isEmpty()) { list.pop(); } } catch (NoSuchElementException e) { // this shouldn't be possible since we check for empty above and this is thread-isolated logger.debug("No command found to end.", e); } catch (Exception e) { logger.warn("Unable to end command.", e); } } /* package-private */ static int getCommandCount() { return currentCommand.get().size(); } /** * Trieber's algorithm for a concurrent stack * @param */ private static class ConcurrentStack { AtomicReference> top = new AtomicReference>(); public void push(E item) { Node newHead = new Node(item); Node oldHead; do { oldHead = top.get(); newHead.next = oldHead; } while (!top.compareAndSet(oldHead, newHead)); } public E pop() { Node oldHead; Node newHead; do { oldHead = top.get(); if (oldHead == null) { return null; } newHead = oldHead.next; } while (!top.compareAndSet(oldHead, newHead)); return oldHead.item; } public boolean isEmpty() { return top.get() == null; } public int size() { int currentSize = 0; Node current = top.get(); while (current != null) { currentSize++; current = current.next; } return currentSize; } public E peek() { if (top.get() == null) { return null; } else { return top.get().item; } } private class Node { public final E item; public Node next; public Node(E item) { this.item = item; } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy