diff --git a/build.gradle b/build.gradle index 15e60a933..455e95853 100644 --- a/build.gradle +++ b/build.gradle @@ -31,8 +31,8 @@ subprojects { apply plugin: 'nebula.provided-base' apply plugin: 'nebula.compile-api' - sourceCompatibility = 1.6 - targetCompatibility = 1.6 + sourceCompatibility = 1.8 + targetCompatibility = 1.8 diff --git a/hystrix-contrib/hystrix-codahale-metrics-publisher/build.gradle b/hystrix-contrib/hystrix-codahale-metrics-publisher/build.gradle index 7dc39e9f4..b3d20c3d0 100644 --- a/hystrix-contrib/hystrix-codahale-metrics-publisher/build.gradle +++ b/hystrix-contrib/hystrix-codahale-metrics-publisher/build.gradle @@ -1,6 +1,21 @@ +apply plugin: 'maven' + dependencies { compileApi project(':hystrix-core') compileApi 'io.dropwizard.metrics:metrics-core:3.2.2' testCompile 'junit:junit-dep:4.10' testCompile 'org.mockito:mockito-all:1.9.5' } + +uploadArchives { + repositories { + mavenDeployer { + repository(url: "https://clojars.org/repo"){ + authentication(userName: "", password: "") + } + pom.version = '1.5.11-22' + pom.groupId = 'org.hystrix' + pom.artifactId = 'hystrix-codahale-metrics-publisher' + } + } +} diff --git a/hystrix-contrib/hystrix-codahale-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/codahalemetricspublisher/HystrixCodaHaleMetricsPublisherCommand.java b/hystrix-contrib/hystrix-codahale-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/codahalemetricspublisher/HystrixCodaHaleMetricsPublisherCommand.java index 88bbef9c3..e8542ea29 100644 --- a/hystrix-contrib/hystrix-codahale-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/codahalemetricspublisher/HystrixCodaHaleMetricsPublisherCommand.java +++ b/hystrix-contrib/hystrix-codahale-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/codahalemetricspublisher/HystrixCodaHaleMetricsPublisherCommand.java @@ -333,6 +333,12 @@ public Integer getValue() { return metrics.getExecutionTimePercentile(90); } }); + metricRegistry.register(createMetricName("latencyExecute_percentile_95"), new Gauge() { + @Override + public Integer getValue() { + return metrics.getExecutionTimePercentile(95); + } + }); metricRegistry.register(createMetricName("latencyExecute_percentile_99"), new Gauge() { @Override public Integer getValue() { @@ -382,6 +388,12 @@ public Integer getValue() { return metrics.getTotalTimePercentile(90); } }); + metricRegistry.register(createMetricName("latencyTotal_percentile_95"), new Gauge() { + @Override + public Integer getValue() { + return metrics.getTotalTimePercentile(95); + } + }); metricRegistry.register(createMetricName("latencyTotal_percentile_99"), new Gauge() { @Override public Integer getValue() { diff --git a/hystrix-contrib/hystrix-codahale-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/codahalemetricspublisher/HystrixCodaHaleMetricsPublisherThreadPool.java b/hystrix-contrib/hystrix-codahale-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/codahalemetricspublisher/HystrixCodaHaleMetricsPublisherThreadPool.java index 79fafcb4d..9ef28bdc8 100644 --- a/hystrix-contrib/hystrix-codahale-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/codahalemetricspublisher/HystrixCodaHaleMetricsPublisherThreadPool.java +++ b/hystrix-contrib/hystrix-codahale-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/codahalemetricspublisher/HystrixCodaHaleMetricsPublisherThreadPool.java @@ -22,6 +22,8 @@ import com.netflix.hystrix.HystrixThreadPoolProperties; import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisherThreadPool; import com.netflix.hystrix.util.HystrixRollingNumberEvent; +import java.util.ArrayList; +import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,6 +37,7 @@ public class HystrixCodaHaleMetricsPublisherThreadPool implements HystrixMetrics private final MetricRegistry metricRegistry; private final String metricGroup; private final String metricType; + private List metricsList = new ArrayList<>(); static final Logger logger = LoggerFactory.getLogger(HystrixCodaHaleMetricsPublisherThreadPool.class); @@ -142,14 +145,14 @@ public Number getValue() { metricRegistry.register(createMetricName("propertyValue_corePoolSize"), new Gauge() { @Override public Number getValue() { - return properties.coreSize().get(); + return metrics.getCurrentCorePoolSize(); } }); metricRegistry.register(createMetricName("propertyValue_maximumSize"), new Gauge() { @Override public Number getValue() { - return properties.maximumSize().get(); + return metrics.getCurrentMaximumPoolSize(); } }); @@ -183,6 +186,8 @@ public Number getValue() { } protected String createMetricName(String name) { - return MetricRegistry.name(metricGroup, metricType, name); + String metricName = MetricRegistry.name(metricGroup, metricType, name); + metricsList.add(metricName); + return metricName; } } diff --git a/hystrix-contrib/hystrix-yammer-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/yammermetricspublisher/HystrixYammerMetricsPublisherThreadPool.java b/hystrix-contrib/hystrix-yammer-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/yammermetricspublisher/HystrixYammerMetricsPublisherThreadPool.java index aa2b99654..be2cec631 100644 --- a/hystrix-contrib/hystrix-yammer-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/yammermetricspublisher/HystrixYammerMetricsPublisherThreadPool.java +++ b/hystrix-contrib/hystrix-yammer-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/yammermetricspublisher/HystrixYammerMetricsPublisherThreadPool.java @@ -26,6 +26,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; +import java.util.List; + /** * Implementation of {@link HystrixMetricsPublisherThreadPool} using Yammer Metrics (https://github.com/codahale/metrics) */ @@ -36,6 +39,7 @@ public class HystrixYammerMetricsPublisherThreadPool implements HystrixMetricsPu private final MetricsRegistry metricsRegistry; private final String metricGroup; private final String metricType; + private List metricsList = new ArrayList<>(); static final Logger logger = LoggerFactory.getLogger(HystrixYammerMetricsPublisherThreadPool.class); diff --git a/hystrix-core/build.gradle b/hystrix-core/build.gradle index 8955c78e9..5ffcf17f5 100644 --- a/hystrix-core/build.gradle +++ b/hystrix-core/build.gradle @@ -1,3 +1,22 @@ +buildscript { + repositories { + jcenter() + maven{ + name 'clojars' + url 'http://clojars.org/repo' + } + } + dependencies { + classpath 'com.netflix.nebula:nebula-clojure-plugin:4.0.1' + } +} +apply plugin: 'nebula.clojure' // this is a wrapper around clojuresque to make it behave well with other plugins + +repositories { + mavenCentral() + clojarsRepo() +} + apply plugin: 'osgi' apply plugin: 'me.champeau.gradle.jmh' @@ -11,6 +30,23 @@ dependencies { } +version = '1.5.0' +apply plugin: "groovy" +apply plugin: 'maven' + +uploadArchives { + repositories { + mavenDeployer { + repository(url: "https://clojars.org/repo"){ + authentication(userName: "", password: "") + } + pom.version = '1.5.11-22' + pom.groupId = 'org.hystrix' + pom.artifactId = 'hystrix-core' + } + } +} + javadoc { // the exclude isn't working, nor is there a subPackages options as docs suggest there should be // we do not want the com.netflix.hystrix.util package include diff --git a/hystrix-core/src/jmh/java/com/netflix/hystrix/perf/CollapserPerfTest.java b/hystrix-core/src/jmh/java/com/netflix/hystrix/perf/CollapserPerfTest.java index 3e155514b..2aafcd30d 100644 --- a/hystrix-core/src/jmh/java/com/netflix/hystrix/perf/CollapserPerfTest.java +++ b/hystrix-core/src/jmh/java/com/netflix/hystrix/perf/CollapserPerfTest.java @@ -36,7 +36,6 @@ import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.infra.Blackhole; import rx.Observable; -import rx.Subscription; import java.util.ArrayList; import java.util.Collection; @@ -52,7 +51,7 @@ public static class ThreadPoolState { public void setUp() { hystrixThreadPool = new HystrixThreadPool.HystrixThreadPoolDefault( HystrixThreadPoolKey.Factory.asKey("PERF") - , HystrixThreadPoolProperties.Setter().withCoreSize(100)); + , HystrixThreadPoolProperties.Setter().withCoreSize(100), false); } @TearDown diff --git a/hystrix-core/src/jmh/java/com/netflix/hystrix/perf/CommandExecutionPerfTest.java b/hystrix-core/src/jmh/java/com/netflix/hystrix/perf/CommandExecutionPerfTest.java index cc40587a7..56d93f696 100644 --- a/hystrix-core/src/jmh/java/com/netflix/hystrix/perf/CommandExecutionPerfTest.java +++ b/hystrix-core/src/jmh/java/com/netflix/hystrix/perf/CommandExecutionPerfTest.java @@ -227,7 +227,7 @@ public static class ThreadPoolState { public void setUp() { hystrixThreadPool = new HystrixThreadPool.HystrixThreadPoolDefault( HystrixThreadPoolKey.Factory.asKey("PERF") - , HystrixThreadPoolProperties.Setter().withCoreSize(100)); + , HystrixThreadPoolProperties.Setter().withCoreSize(100), false); } @TearDown diff --git a/hystrix-core/src/main/java/com/netflix/hystrix/HystrixThreadPool.java b/hystrix-core/src/main/java/com/netflix/hystrix/HystrixThreadPool.java index c68641dbf..46c56c48b 100644 --- a/hystrix-core/src/main/java/com/netflix/hystrix/HystrixThreadPool.java +++ b/hystrix-core/src/main/java/com/netflix/hystrix/HystrixThreadPool.java @@ -92,6 +92,13 @@ public interface HystrixThreadPool { */ /* package */final static ConcurrentHashMap threadPools = new ConcurrentHashMap(); + /* + * Use the String from HystrixThreadPoolKey.name() instead of the HystrixThreadPoolKey instance as it's just an interface and we can't ensure the object + * we receive implements hashcode/equals correctly and do not want the default hashcode/equals which would create a new threadpool for every object we get even if the name is the same + */ + final static ConcurrentHashMap threadPoolProperties = + new ConcurrentHashMap(); + /** * Get the {@link HystrixThreadPool} instance for a given {@link HystrixThreadPoolKey}. *

@@ -102,17 +109,25 @@ public interface HystrixThreadPool { /* package */static HystrixThreadPool getInstance(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties.Setter propertiesBuilder) { // get the key to use instead of using the object itself so that if people forget to implement equals/hashcode things will still work String key = threadPoolKey.name(); - + HystrixThreadPoolProperties.Setter oldPropertiesBuilder = threadPoolProperties.get(key); + boolean updated = oldPropertiesBuilder != null && !oldPropertiesBuilder.equals(propertiesBuilder); // this should find it for all but the first time HystrixThreadPool previouslyCached = threadPools.get(key); if (previouslyCached != null) { + if(updated && previouslyCached instanceof HystrixThreadPoolDefault){ + threadPoolProperties.put(key, propertiesBuilder); + ((HystrixThreadPoolDefault)previouslyCached).touchConfig(threadPoolKey, propertiesBuilder); + } return previouslyCached; } // if we get here this is the first time so we need to initialize synchronized (HystrixThreadPool.class) { if (!threadPools.containsKey(key)) { - threadPools.put(key, new HystrixThreadPoolDefault(threadPoolKey, propertiesBuilder)); + threadPools.put(key, new HystrixThreadPoolDefault(threadPoolKey, propertiesBuilder, updated)); + if(propertiesBuilder != null){ + threadPoolProperties.put(key, propertiesBuilder); + } } } return threadPools.get(key); @@ -162,14 +177,15 @@ public interface HystrixThreadPool { /* package */static class HystrixThreadPoolDefault implements HystrixThreadPool { private static final Logger logger = LoggerFactory.getLogger(HystrixThreadPoolDefault.class); - private final HystrixThreadPoolProperties properties; + private HystrixThreadPoolProperties properties; private final BlockingQueue queue; private final ThreadPoolExecutor threadPool; private final HystrixThreadPoolMetrics metrics; private final int queueSize; - public HystrixThreadPoolDefault(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties.Setter propertiesDefaults) { - this.properties = HystrixPropertiesFactory.getThreadPoolProperties(threadPoolKey, propertiesDefaults); + public HystrixThreadPoolDefault(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties.Setter propertiesDefaults, + boolean updated) { + this.properties = HystrixPropertiesFactory.getThreadPoolProperties(threadPoolKey, propertiesDefaults, updated); HystrixConcurrencyStrategy concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy(); this.queueSize = properties.maxQueueSize().get(); @@ -206,6 +222,12 @@ public Scheduler getScheduler(Func0 shouldInterruptThread) { return new HystrixContextScheduler(HystrixPlugins.getInstance().getConcurrencyStrategy(), this, shouldInterruptThread); } + private void touchConfig(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties.Setter newProperties) { + this.properties = HystrixPropertiesFactory.getThreadPoolProperties(threadPoolKey, newProperties, + true); + touchConfig(); + } + // allow us to change things via fast-properties by setting it each time private void touchConfig() { final int dynamicCoreSize = properties.coreSize().get(); @@ -219,9 +241,10 @@ private void touchConfig() { dynamicMaximumSize = dynamicCoreSize; maxTooLow = true; } - // In JDK 6, setCorePoolSize and setMaximumPoolSize will execute a lock operation. Avoid them if the pool size is not changed. if (threadPool.getCorePoolSize() != dynamicCoreSize || (allowSizesToDiverge && threadPool.getMaximumPoolSize() != dynamicMaximumSize)) { + logger.info("Old core pool : {}, new core pool : {}, old max : {}, new max {}" , + threadPool.getCorePoolSize(), dynamicCoreSize, threadPool.getMaximumPoolSize(), dynamicMaximumSize); if (maxTooLow) { logger.error("Hystrix ThreadPool configuration for : " + metrics.getThreadPoolKey().name() + " is trying to set coreSize = " + dynamicCoreSize + " and maximumSize = " + configuredMaximumSize + ". Maximum size will be set to " + diff --git a/hystrix-core/src/main/java/com/netflix/hystrix/HystrixThreadPoolProperties.java b/hystrix-core/src/main/java/com/netflix/hystrix/HystrixThreadPoolProperties.java index 56f4e6307..edec0b656 100644 --- a/hystrix-core/src/main/java/com/netflix/hystrix/HystrixThreadPoolProperties.java +++ b/hystrix-core/src/main/java/com/netflix/hystrix/HystrixThreadPoolProperties.java @@ -321,8 +321,31 @@ public Setter withMetricsRollingStatisticalWindowBuckets(int value) { return this; } + @Override + public boolean equals(Object o) { + if(this == o) + return true; + if(!(o instanceof Setter)) + return false; + + Setter setter = (Setter)o; + + if(!coreSize.equals(setter.coreSize)) + return false; + if(!maximumSize.equals(setter.maximumSize)) + return false; + if(!keepAliveTimeMinutes.equals(setter.keepAliveTimeMinutes)) + return false; + return maxQueueSize.equals(setter.maxQueueSize); + } - - + @Override + public int hashCode() { + int result = coreSize.hashCode(); + result = 31 * result + maximumSize.hashCode(); + result = 31 * result + keepAliveTimeMinutes.hashCode(); + result = 31 * result + maxQueueSize.hashCode(); + return result; + } } } diff --git a/hystrix-core/src/main/java/com/netflix/hystrix/strategy/properties/HystrixPropertiesFactory.java b/hystrix-core/src/main/java/com/netflix/hystrix/strategy/properties/HystrixPropertiesFactory.java index 792d7ab09..190f61798 100644 --- a/hystrix-core/src/main/java/com/netflix/hystrix/strategy/properties/HystrixPropertiesFactory.java +++ b/hystrix-core/src/main/java/com/netflix/hystrix/strategy/properties/HystrixPropertiesFactory.java @@ -95,28 +95,29 @@ public static HystrixCommandProperties getCommandProperties(HystrixCommandKey ke * Pass-thru to {@link HystrixPropertiesStrategy#getThreadPoolProperties} implementation. * @param builder * Pass-thru to {@link HystrixPropertiesStrategy#getThreadPoolProperties} implementation. + * @param updated * @return {@link HystrixThreadPoolProperties} instance */ - public static HystrixThreadPoolProperties getThreadPoolProperties(HystrixThreadPoolKey key, HystrixThreadPoolProperties.Setter builder) { + public static HystrixThreadPoolProperties getThreadPoolProperties(HystrixThreadPoolKey key, HystrixThreadPoolProperties.Setter builder, + boolean updated) { HystrixPropertiesStrategy hystrixPropertiesStrategy = HystrixPlugins.getInstance().getPropertiesStrategy(); String cacheKey = hystrixPropertiesStrategy.getThreadPoolPropertiesCacheKey(key, builder); if (cacheKey != null) { HystrixThreadPoolProperties properties = threadPoolProperties.get(cacheKey); - if (properties != null) { + if (properties != null && !updated) { return properties; } else { if (builder == null) { builder = HystrixThreadPoolProperties.Setter(); } - // create new instance - properties = hystrixPropertiesStrategy.getThreadPoolProperties(key, builder); - // cache and return - HystrixThreadPoolProperties existing = threadPoolProperties.putIfAbsent(cacheKey, properties); - if (existing == null) { + synchronized (HystrixPropertiesFactory.class){ + // create new instance + properties = hystrixPropertiesStrategy.getThreadPoolProperties(key, builder); + // cache and return + threadPoolProperties.put(cacheKey, properties); return properties; - } else { - return existing; } + } } else { // no cacheKey so we generate it with caching diff --git a/hystrix-core/src/test/java/com/netflix/hystrix/HystrixThreadPoolTest.java b/hystrix-core/src/test/java/com/netflix/hystrix/HystrixThreadPoolTest.java index faf22f9be..7aec75dd6 100644 --- a/hystrix-core/src/test/java/com/netflix/hystrix/HystrixThreadPoolTest.java +++ b/hystrix-core/src/test/java/com/netflix/hystrix/HystrixThreadPoolTest.java @@ -105,9 +105,9 @@ public HystrixMetricsPublisherThreadPool getMetricsPublisherForThreadPool(Hystri }); HystrixThreadPoolKey threadPoolKey = HystrixThreadPoolKey.Factory.asKey("threadPoolFactoryConcurrencyTest"); HystrixThreadPool poolOne = new HystrixThreadPool.HystrixThreadPoolDefault( - threadPoolKey, HystrixThreadPoolPropertiesTest.getUnitTestPropertiesBuilder()); + threadPoolKey, HystrixThreadPoolPropertiesTest.getUnitTestPropertiesBuilder(), false); HystrixThreadPool poolTwo = new HystrixThreadPool.HystrixThreadPoolDefault( - threadPoolKey, HystrixThreadPoolPropertiesTest.getUnitTestPropertiesBuilder()); + threadPoolKey, HystrixThreadPoolPropertiesTest.getUnitTestPropertiesBuilder(), false); assertThat(poolOne.getExecutor(), is(poolTwo.getExecutor())); //Now that we get the threadPool from the metrics object, this will always be equal HystrixMetricsPublisherThreadPoolContainer hystrixMetricsPublisherThreadPool =