/** * Get an instance of {@link HystrixMetricsPublisherThreadPool} with the given factory {@link HystrixMetricsPublisher} implementation for each {@link HystrixThreadPool} instance. * * @param threadPoolKey * Pass-thru to {@link HystrixMetricsPublisher#getMetricsPublisherForThreadPool} implementation * @param metrics * Pass-thru to {@link HystrixMetricsPublisher#getMetricsPublisherForThreadPool} implementation * @param properties * Pass-thru to {@link HystrixMetricsPublisher#getMetricsPublisherForThreadPool} implementation * @return {@link HystrixMetricsPublisherThreadPool} instance */ public static HystrixMetricsPublisherThreadPool createOrRetrievePublisherForThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolMetrics metrics, HystrixThreadPoolProperties properties) { return SINGLETON.getPublisherForThreadPool(threadPoolKey, metrics, properties); }
/** * Get an instance of {@link HystrixMetricsPublisherCollapser} with the given factory {@link HystrixMetricsPublisher} implementation for each {@link HystrixCollapser} instance. * * @param collapserKey * Pass-thru to {@link HystrixMetricsPublisher#getMetricsPublisherForCollapser} implementation * @param metrics * Pass-thru to {@link HystrixMetricsPublisher#getMetricsPublisherForCollapser} implementation * @param properties * Pass-thru to {@link HystrixMetricsPublisher#getMetricsPublisherForCollapser} implementation * @return {@link HystrixMetricsPublisherCollapser} instance */ public static HystrixMetricsPublisherCollapser createOrRetrievePublisherForCollapser(HystrixCollapserKey collapserKey, HystrixCollapserMetrics metrics, HystrixCollapserProperties properties) { return SINGLETON.getPublisherForCollapser(collapserKey, metrics, properties); }
/** * Get an instance of {@link HystrixMetricsPublisherCommand} with the given factory {@link HystrixMetricsPublisher} implementation for each {@link HystrixCommand} instance. * * @param commandKey * Pass-thru to {@link HystrixMetricsPublisher#getMetricsPublisherForCommand} implementation * @param commandOwner * Pass-thru to {@link HystrixMetricsPublisher#getMetricsPublisherForCommand} implementation * @param metrics * Pass-thru to {@link HystrixMetricsPublisher#getMetricsPublisherForCommand} implementation * @param circuitBreaker * Pass-thru to {@link HystrixMetricsPublisher#getMetricsPublisherForCommand} implementation * @param properties * Pass-thru to {@link HystrixMetricsPublisher#getMetricsPublisherForCommand} implementation * @return {@link HystrixMetricsPublisherCommand} instance */ public static HystrixMetricsPublisherCommand createOrRetrievePublisherForCommand(HystrixCommandKey commandKey, HystrixCommandGroupKey commandOwner, HystrixCommandMetrics metrics, HystrixCircuitBreaker circuitBreaker, HystrixCommandProperties properties) { return SINGLETON.getPublisherForCommand(commandKey, commandOwner, metrics, circuitBreaker, properties); }
/* package */ HystrixMetricsPublisherThreadPool getPublisherForThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolMetrics metrics, HystrixThreadPoolProperties properties) { // attempt to retrieve from cache first HystrixMetricsPublisherThreadPool publisher = threadPoolPublishers.get(threadPoolKey.name()); if (publisher != null) { return publisher; } // it doesn't exist so we need to create it publisher = HystrixPlugins.getInstance().getMetricsPublisher().getMetricsPublisherForThreadPool(threadPoolKey, metrics, properties); // attempt to store it (race other threads) HystrixMetricsPublisherThreadPool existing = threadPoolPublishers.putIfAbsent(threadPoolKey.name(), publisher); if (existing == null) { // we won the thread-race to store the instance we created so initialize it publisher.initialize(); // done registering, return instance that got cached return publisher; } else { // we lost so return 'existing' and let the one we created be garbage collected // without calling initialize() on it return existing; } }
/* package */ HystrixMetricsPublisherCommand getPublisherForCommand(HystrixCommandKey commandKey, HystrixCommandGroupKey commandOwner, HystrixCommandMetrics metrics, HystrixCircuitBreaker circuitBreaker, HystrixCommandProperties properties) { // attempt to retrieve from cache first HystrixMetricsPublisherCommand publisher = commandPublishers.get(commandKey.name()); if (publisher != null) { return publisher; } else { synchronized (this) { HystrixMetricsPublisherCommand existingPublisher = commandPublishers.get(commandKey.name()); if (existingPublisher != null) { return existingPublisher; } else { HystrixMetricsPublisherCommand newPublisher = HystrixPlugins.getInstance().getMetricsPublisher().getMetricsPublisherForCommand(commandKey, commandOwner, metrics, circuitBreaker, properties); commandPublishers.putIfAbsent(commandKey.name(), newPublisher); newPublisher.initialize(); return newPublisher; } } } }
@Test public void testMetricsPublisherReset() { // precondition: HystrixMetricsPublisherFactory class is not loaded. Calling HystrixPlugins.reset() here should be good enough to run this with other tests. // set first custom publisher HystrixCommandKey key = HystrixCommandKey.Factory.asKey("key"); HystrixMetricsPublisherCommand firstCommand = new HystrixMetricsPublisherCommandDefault(key, null, null, null, null); HystrixMetricsPublisher firstPublisher = new CustomPublisher(firstCommand); HystrixPlugins.getInstance().registerMetricsPublisher(firstPublisher); // ensure that first custom publisher is used HystrixMetricsPublisherCommand cmd = HystrixMetricsPublisherFactory.createOrRetrievePublisherForCommand(key, null, null, null, null); assertSame(firstCommand, cmd); // reset, then change to second custom publisher HystrixPlugins.reset(); HystrixMetricsPublisherCommand secondCommand = new HystrixMetricsPublisherCommandDefault(key, null, null, null, null); HystrixMetricsPublisher secondPublisher = new CustomPublisher(secondCommand); HystrixPlugins.getInstance().registerMetricsPublisher(secondPublisher); // ensure that second custom publisher is used cmd = HystrixMetricsPublisherFactory.createOrRetrievePublisherForCommand(key, null, null, null, null); assertNotSame(firstCommand, cmd); assertSame(secondCommand, cmd); }
@Override public void run() { factory.getPublisherForCommand(TestCommandKey.TEST_A, null, null, null, null); factory.getPublisherForCommand(TestCommandKey.TEST_B, null, null, null, null); factory.getPublisherForThreadPool(TestThreadPoolKey.TEST_A, null, null); }
/* package */ HystrixMetricsPublisherCollapser getPublisherForCollapser(HystrixCollapserKey collapserKey, HystrixCollapserMetrics metrics, HystrixCollapserProperties properties) { // attempt to retrieve from cache first HystrixMetricsPublisherCollapser publisher = collapserPublishers.get(collapserKey.name()); if (publisher != null) { return publisher; } // it doesn't exist so we need to create it publisher = HystrixPlugins.getInstance().getMetricsPublisher().getMetricsPublisherForCollapser(collapserKey, metrics, properties); // attempt to store it (race other threads) HystrixMetricsPublisherCollapser existing = collapserPublishers.putIfAbsent(collapserKey.name(), publisher); if (existing == null) { // we won the thread-race to store the instance we created so initialize it publisher.initialize(); // done registering, return instance that got cached return publisher; } else { // we lost so return 'existing' and let the one we created be garbage collected // without calling initialize() on it return existing; } }
public HystrixThreadPoolDefault(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties.Setter propertiesDefaults) { this.properties = HystrixPropertiesFactory.getThreadPoolProperties(threadPoolKey, propertiesDefaults); HystrixConcurrencyStrategy concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy(); this.queueSize = properties.maxQueueSize().get(); this.metrics = HystrixThreadPoolMetrics.getInstance(threadPoolKey, concurrencyStrategy.getThreadPool(threadPoolKey, properties), properties); this.threadPool = this.metrics.getThreadPool(); this.queue = this.threadPool.getQueue(); /* strategy: HystrixMetricsPublisherThreadPool */ HystrixMetricsPublisherFactory.createOrRetrievePublisherForThreadPool(threadPoolKey, this.metrics, this.properties); }
final TestHystrixMetricsPublisher publisher = new TestHystrixMetricsPublisher(); HystrixPlugins.getInstance().registerMetricsPublisher(publisher); final HystrixMetricsPublisherFactory factory = new HystrixMetricsPublisherFactory(); ArrayList<Thread> threads = new ArrayList<Thread>(); for (int i = 0; i < 20; i++) {
/** * Construct an implementation of {@link HystrixMetricsPublisherCommand} for {@link HystrixCommand} instances having key {@link HystrixCommandKey}. * <p> * This will be invoked once per {@link HystrixCommandKey} instance. * <p> * <b>Default Implementation</b> * <p> * Return instance of {@link HystrixMetricsPublisherCommandDefault} * * @param commandKey * {@link HystrixCommandKey} representing the name or type of {@link HystrixCommand} * @param commandGroupKey * {@link HystrixCommandGroupKey} of {@link HystrixCommand} * @param metrics * {@link HystrixCommandMetrics} instance tracking metrics for {@link HystrixCommand} instances having the key as defined by {@link HystrixCommandKey} * @param circuitBreaker * {@link HystrixCircuitBreaker} instance for {@link HystrixCommand} instances having the key as defined by {@link HystrixCommandKey} * @param properties * {@link HystrixCommandProperties} instance for {@link HystrixCommand} instances having the key as defined by {@link HystrixCommandKey} * @return instance of {@link HystrixMetricsPublisherCommand} that will have its <code>initialize</code> method invoked once. */ public HystrixMetricsPublisherCommand getMetricsPublisherForCommand(HystrixCommandKey commandKey, HystrixCommandGroupKey commandGroupKey, HystrixCommandMetrics metrics, HystrixCircuitBreaker circuitBreaker, HystrixCommandProperties properties) { return new HystrixMetricsPublisherCommandDefault(commandKey, commandGroupKey, metrics, circuitBreaker, properties); }
/** * Resets the SINGLETON object. * Clears all state from publishers. If new requests come in instances will be recreated. * */ public static void reset() { SINGLETON = new HystrixMetricsPublisherFactory(); SINGLETON.commandPublishers.clear(); SINGLETON.threadPoolPublishers.clear(); SINGLETON.collapserPublishers.clear(); }
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(); 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 semaphore override if applicable */ this.fallbackSemaphoreOverride = fallbackSemaphore; /* execution semaphore override if applicable */ this.executionSemaphoreOverride = executionSemaphore; }
HystrixMetricsPublisherFactory.createOrRetrievePublisherForCollapser(collapserKey, this.metrics, properties);
/** * Construct an implementation of {@link HystrixMetricsPublisherCollapser} for {@link HystrixCollapser} instances having key {@link HystrixCollapserKey}. * <p> * This will be invoked once per {@link HystrixCollapserKey} instance. * <p> * <b>Default Implementation</b> * <p> * Return instance of {@link HystrixMetricsPublisherCollapserDefault} * * @param collapserKey * {@link HystrixCollapserKey} representing the name or type of {@link HystrixCollapser} * @param metrics * {@link HystrixCollapserMetrics} instance tracking metrics for the {@link HystrixCollapser} instance having the key as defined by {@link HystrixCollapserKey} * @param properties * {@link HystrixCollapserProperties} instance for the {@link HystrixCollapser} instance having the key as defined by {@link HystrixCollapserKey} * @return instance of {@link HystrixMetricsPublisherCollapser} that will have its <code>initialize</code> method invoked once. */ public HystrixMetricsPublisherCollapser getMetricsPublisherForCollapser(HystrixCollapserKey collapserKey, HystrixCollapserMetrics metrics, HystrixCollapserProperties properties) { return new HystrixMetricsPublisherCollapserDefault(collapserKey, metrics, properties); }
/** * Construct an implementation of {@link HystrixMetricsPublisherThreadPool} for {@link HystrixThreadPool} instances having key {@link HystrixThreadPoolKey}. * <p> * This will be invoked once per {@link HystrixThreadPoolKey} instance. * <p> * <b>Default Implementation</b> * <p> * Return instance of {@link HystrixMetricsPublisherThreadPoolDefault} * * @param threadPoolKey * {@link HystrixThreadPoolKey} representing the name or type of {@link HystrixThreadPool} * @param metrics * {@link HystrixThreadPoolMetrics} instance tracking metrics for the {@link HystrixThreadPool} instance having the key as defined by {@link HystrixThreadPoolKey} * @param properties * {@link HystrixThreadPoolProperties} instance for the {@link HystrixThreadPool} instance having the key as defined by {@link HystrixThreadPoolKey} * @return instance of {@link HystrixMetricsPublisherThreadPool} that will have its <code>initialize</code> method invoked once. */ public HystrixMetricsPublisherThreadPool getMetricsPublisherForThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolMetrics metrics, HystrixThreadPoolProperties properties) { return new HystrixMetricsPublisherThreadPoolDefault(threadPoolKey, metrics, properties); }
/** * Retrieve instance of {@link HystrixMetricsPublisher} to use based on order of precedence as defined in {@link HystrixPlugins} class header. * <p> * Override default by using {@link #registerMetricsPublisher(HystrixMetricsPublisher)} or setting property (via Archaius): <code>hystrix.plugin.HystrixMetricsPublisher.implementation</code> with the full * classname to load. * * @return {@link HystrixMetricsPublisher} implementation to use */ public HystrixMetricsPublisher getMetricsPublisher() { if (metricsPublisher.get() == null) { // check for an implementation from Archaius first Object impl = getPluginImplementation(HystrixMetricsPublisher.class); if (impl == null) { // nothing set via Archaius so initialize with default metricsPublisher.compareAndSet(null, HystrixMetricsPublisherDefault.getInstance()); // we don't return from here but call get() again in case of thread-race so the winner will always get returned } else { // we received an implementation from Archaius so use it metricsPublisher.compareAndSet(null, (HystrixMetricsPublisher) impl); } } return metricsPublisher.get(); }
/** * Reset all of the HystrixPlugins to null. You may invoke this directly, or it also gets invoked via <code>Hystrix.reset()</code> */ public static void reset() { getInstance().notifier.set(null); getInstance().concurrencyStrategy.set(null); getInstance().metricsPublisher.set(null); getInstance().propertiesFactory.set(null); getInstance().commandExecutionHook.set(null); HystrixMetricsPublisherFactory.reset(); }
@Test public void ensureThreadPoolInstanceIsTheOneRegisteredWithMetricsPublisherAndThreadPoolCache() throws IllegalAccessException, NoSuchFieldException { HystrixPlugins.getInstance().registerMetricsPublisher(new HystrixMetricsPublisher() { @Override public HystrixMetricsPublisherThreadPool getMetricsPublisherForThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolMetrics metrics, HystrixThreadPoolProperties properties) { return new HystrixMetricsPublisherThreadPoolContainer(metrics); } }); HystrixThreadPoolKey threadPoolKey = HystrixThreadPoolKey.Factory.asKey("threadPoolFactoryConcurrencyTest"); HystrixThreadPool poolOne = new HystrixThreadPool.HystrixThreadPoolDefault( threadPoolKey, HystrixThreadPoolPropertiesTest.getUnitTestPropertiesBuilder()); HystrixThreadPool poolTwo = new HystrixThreadPool.HystrixThreadPoolDefault( threadPoolKey, HystrixThreadPoolPropertiesTest.getUnitTestPropertiesBuilder()); assertThat(poolOne.getExecutor(), is(poolTwo.getExecutor())); //Now that we get the threadPool from the metrics object, this will always be equal HystrixMetricsPublisherThreadPoolContainer hystrixMetricsPublisherThreadPool = (HystrixMetricsPublisherThreadPoolContainer)HystrixMetricsPublisherFactory .createOrRetrievePublisherForThreadPool(threadPoolKey, null, null); ThreadPoolExecutor threadPoolExecutor = hystrixMetricsPublisherThreadPool.getHystrixThreadPoolMetrics().getThreadPool(); //assert that both HystrixThreadPools share the same ThreadPoolExecutor as the one in HystrixMetricsPublisherThreadPool assertTrue(threadPoolExecutor.equals(poolOne.getExecutor()) && threadPoolExecutor.equals(poolTwo.getExecutor())); assertFalse(threadPoolExecutor.isShutdown()); //Now the HystrixThreadPool ALWAYS has the same reference to the ThreadPoolExecutor so that it no longer matters which //wins to be inserted into the HystrixThreadPool.Factory.threadPools cache. }
HystrixMetricsPublisherFactory.createOrRetrievePublisherForCollapser(collapserKey, this.metrics, properties);