Skip to content

Commit

Permalink
Add HystrixThreadPoolProperties#actualMaximumSize()
Browse files Browse the repository at this point in the history
This centralizes the logic on how to determine the correct value to actually set the threadpool's max to.
It now treats HystrixThreadPoolProperties#maximumSize() as the value configured (but possibly not used)
  • Loading branch information
mattrjacobs committed Dec 20, 2016
1 parent 362abc0 commit 15f44f3
Show file tree
Hide file tree
Showing 9 changed files with 208 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,13 @@ public Number getValue() {
}
});

metricRegistry.register(createMetricName("propertyValue_actualMaximumSize"), new Gauge<Number>() {
@Override
public Number getValue() {
return properties.maximumSize().get();
}
});

metricRegistry.register(createMetricName("propertyValue_keepAliveTimeInMinutes"), new Gauge<Number>() {
@Override
public Number getValue() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ private static void writeThreadPoolConfigJson(JsonGenerator json, HystrixThreadP
json.writeObjectFieldStart(threadPoolKey.name());
json.writeNumberField("coreSize", threadPoolConfig.getCoreSize());
json.writeNumberField("maximumSize", threadPoolConfig.getMaximumSize());
json.writeNumberField("actualMaximumSize", threadPoolConfig.getActualMaximumSize());
json.writeNumberField("maxQueueSize", threadPoolConfig.getMaxQueueSize());
json.writeNumberField("queueRejectionThreshold", threadPoolConfig.getQueueRejectionThreshold());
json.writeNumberField("keepAliveTimeInMinutes", threadPoolConfig.getKeepAliveTimeInMinutes());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,13 @@ public Number getValue() {
}
});

monitors.add(new InformationalMetric<Number>(MonitorConfig.builder("propertyValue_actualMaximumSize").build()) {
@Override
public Number getValue() {
return properties.actualMaximumSize();
}
});

monitors.add(new InformationalMetric<Number>(MonitorConfig.builder("propertyValue_keepAliveTimeInMinutes").build()) {
@Override
public Number getValue() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,13 @@ public Number value() {
}
});

metricsRegistry.newGauge(createMetricName("propertyValue_actualMaximumSize"), new Gauge<Number>() {
@Override
public Number value() {
return properties.actualMaximumSize();
}
});

metricsRegistry.newGauge(createMetricName("propertyValue_keepAliveTimeInMinutes"), new Gauge<Number>() {
@Override
public Number value() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,31 +209,26 @@ public Scheduler getScheduler(Func0<Boolean> shouldInterruptThread) {
// allow us to change things via fast-properties by setting it each time
private void touchConfig() {
final int dynamicCoreSize = properties.coreSize().get();
final int dynamicMaximumSize = properties.maximumSize().get();
int updatedMaximumSize = dynamicMaximumSize;
final int configuredMaximumSize = properties.maximumSize().get();
int dynamicMaximumSize = properties.actualMaximumSize();
final boolean allowSizesToDiverge = properties.getAllowMaximumSizeToDivergeFromCoreSize().get();
boolean maxTooLow = false;

if (allowSizesToDiverge && dynamicMaximumSize < dynamicCoreSize) {
if (allowSizesToDiverge && configuredMaximumSize < dynamicCoreSize) {
//if user sets maximum < core (or defaults get us there), we need to maintain invariant of core <= maximum
updatedMaximumSize = dynamicCoreSize;
dynamicMaximumSize = dynamicCoreSize;
maxTooLow = true;
}

if (!allowSizesToDiverge) {
//if user has not opted in to allowing sizes to diverge, ensure maximum == core
updatedMaximumSize = dynamicCoreSize;
}

// 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() != updatedMaximumSize)) {
if (threadPool.getCorePoolSize() != dynamicCoreSize || (allowSizesToDiverge && threadPool.getMaximumPoolSize() != dynamicMaximumSize)) {
if (maxTooLow) {
logger.error("Hystrix ThreadPool configuration for : " + metrics.getThreadPoolKey().name() + " is trying to set coreSize = " +
dynamicCoreSize + " and maximumSize = " + dynamicMaximumSize + ". Maximum size will be set to " +
dynamicCoreSize + ", the coreSize value, since it must be equal to or greater than the coreSize value");
dynamicCoreSize + " and maximumSize = " + configuredMaximumSize + ". Maximum size will be set to " +
dynamicMaximumSize + ", the coreSize value, since it must be equal to or greater than the coreSize value");
}
threadPool.setCorePoolSize(dynamicCoreSize);
threadPool.setMaximumPoolSize(updatedMaximumSize);
threadPool.setMaximumPoolSize(dynamicMaximumSize);
}

threadPool.setKeepAliveTime(properties.keepAliveTimeMinutes().get(), TimeUnit.MINUTES);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,39 @@ public HystrixProperty<Integer> coreSize() {
}

/**
* Maximum thread-pool size that gets passed to {@link ThreadPoolExecutor#setMaximumPoolSize(int)}
* Maximum thread-pool size configured for threadpool. May conflict with other config, so if you need the
* actual value that gets passed to {@link ThreadPoolExecutor#setMaximumPoolSize(int)}, use {@link #actualMaximumSize()}
*
* @return {@code HystrixProperty<Integer>}
*/
public HystrixProperty<Integer> maximumSize() {
return maximumPoolSize;
}

/**
* Given all of the thread pool configuration, what is the actual maximumSize applied to the thread pool
* via {@link ThreadPoolExecutor#setMaximumPoolSize(int)}
*
* Cases:
* 1) allowMaximumSizeToDivergeFromCoreSize == false: maximumSize is set to coreSize
* 2) allowMaximumSizeToDivergeFromCoreSize == true, maximumSize >= coreSize: thread pool has different core/max sizes, so return the configured max
* 3) allowMaximumSizeToDivergeFromCoreSize == true, maximumSize < coreSize: threadpool incorrectly configured, use coreSize for max size
* @return actually configured maximum size of threadpool
*/
public Integer actualMaximumSize() {
final int coreSize = coreSize().get();
final int maximumSize = maximumSize().get();
if (allowMaximumSizeToDivergeFromCoreSize.get()) {
if (coreSize > maximumSize) {
return coreSize;
} else {
return maximumSize;
}
} else {
return coreSize;
}
}

/**
* Keep-alive time in minutes that gets passed to {@link ThreadPoolExecutor#setKeepAliveTime(long, TimeUnit)}
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,53 +19,45 @@
import com.netflix.hystrix.HystrixThreadPoolProperties;

public class HystrixThreadPoolConfiguration {
//The idea is for this object to be serialized off-box. For future-proofing, I'm adding a version so that changing config over time can be handled gracefully
private static final String VERSION = "1";
private final HystrixThreadPoolKey threadPoolKey;
private final int coreSize;
private final int maximumSize;
private final int actualMaximumSize;
private final int maxQueueSize;
private final int queueRejectionThreshold;
private final int keepAliveTimeInMinutes;
private final boolean allowMaximumSizeToDivergeFromCoreSize;
private final int rollingCounterNumberOfBuckets;
private final int rollingCounterBucketSizeInMilliseconds;

public HystrixThreadPoolConfiguration(HystrixThreadPoolKey threadPoolKey, int coreSize, int maximumSize, int maxQueueSize, int queueRejectionThreshold,
private HystrixThreadPoolConfiguration(HystrixThreadPoolKey threadPoolKey, int coreSize, int maximumSize, int actualMaximumSize, int maxQueueSize, int queueRejectionThreshold,
int keepAliveTimeInMinutes, boolean allowMaximumSizeToDivergeFromCoreSize, int rollingCounterNumberOfBuckets,
int rollingCounterBucketSizeInMilliseconds) {
this.threadPoolKey = threadPoolKey;
this.allowMaximumSizeToDivergeFromCoreSize = allowMaximumSizeToDivergeFromCoreSize;
this.coreSize = coreSize;
if (allowMaximumSizeToDivergeFromCoreSize) {
if (coreSize > maximumSize) {
this.maximumSize = coreSize;
} else {
this.maximumSize = maximumSize;
}
} else {
this.maximumSize = coreSize;
}
this.maximumSize = maximumSize;
this.actualMaximumSize = actualMaximumSize;
this.maxQueueSize = maxQueueSize;
this.queueRejectionThreshold = queueRejectionThreshold;
this.keepAliveTimeInMinutes = keepAliveTimeInMinutes;
this.rollingCounterNumberOfBuckets = rollingCounterNumberOfBuckets;
this.rollingCounterBucketSizeInMilliseconds = rollingCounterBucketSizeInMilliseconds;
}

public static HystrixThreadPoolConfiguration sample(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties threadPoolProperties) {
return new HystrixThreadPoolConfiguration(
threadPoolKey,
threadPoolProperties.coreSize().get(),
threadPoolProperties.maximumSize().get(),
threadPoolProperties.maxQueueSize().get(),
threadPoolProperties.queueSizeRejectionThreshold().get(),
threadPoolProperties.keepAliveTimeMinutes().get(),
threadPoolProperties.getAllowMaximumSizeToDivergeFromCoreSize().get(),
private HystrixThreadPoolConfiguration(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties threadPoolProperties) {
this(threadPoolKey, threadPoolProperties.coreSize().get(),
threadPoolProperties.maximumSize().get(), threadPoolProperties.actualMaximumSize(),
threadPoolProperties.maxQueueSize().get(), threadPoolProperties.queueSizeRejectionThreshold().get(),
threadPoolProperties.keepAliveTimeMinutes().get(), threadPoolProperties.getAllowMaximumSizeToDivergeFromCoreSize().get(),
threadPoolProperties.metricsRollingStatisticalWindowBuckets().get(),
threadPoolProperties.metricsRollingStatisticalWindowInMilliseconds().get());
}

public static HystrixThreadPoolConfiguration sample(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties threadPoolProperties) {
return new HystrixThreadPoolConfiguration(threadPoolKey, threadPoolProperties);
}

public HystrixThreadPoolKey getThreadPoolKey() {
return threadPoolKey;
}
Expand All @@ -74,12 +66,25 @@ public int getCoreSize() {
return coreSize;
}

/**
* Simple getter that returns what the `maximumSize` property is configured as
* @return
*/
public int getMaximumSize() {
if (allowMaximumSizeToDivergeFromCoreSize) {
return maximumSize;
} else {
return coreSize;
}
return maximumSize;
}

/**
* Given all of the thread pool configuration, what is the actual maximumSize applied to the thread pool.
*
* Cases:
* 1) allowMaximumSizeToDivergeFromCoreSize == false: maximumSize is set to coreSize
* 2) allowMaximumSizeToDivergeFromCoreSize == true, maximumSize >= coreSize: thread pool has different core/max sizes, so return the configured max
* 3) allowMaximumSizeToDivergeFromCoreSize == true, maximumSize < coreSize: threadpool incorrectly configured, use coreSize for max size
* @return actually configured maximum size of threadpool
*/
public int getActualMaximumSize() {
return this.actualMaximumSize;
}

public int getMaxQueueSize() {
Expand Down
Loading

0 comments on commit 15f44f3

Please sign in to comment.