Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Api degrade #47

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>io.dropwizard.revolver</groupId>
<artifactId>dropwizard-revolver</artifactId>
<version>1.3.7-38-5</version>
<version>1.3.7-38-6</version>
<packaging>jar</packaging>

<name>dropwizard-revolver</name>
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/io/dropwizard/revolver/RevolverBundle.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import io.dropwizard.revolver.core.config.RevolverConfig;
import io.dropwizard.revolver.core.config.RevolverServiceConfig;
import io.dropwizard.revolver.core.config.hystrix.ThreadPoolConfig;
import io.dropwizard.revolver.degrade.DegradeRegistry;
import io.dropwizard.revolver.discovery.RevolverServiceResolver;
import io.dropwizard.revolver.discovery.model.RangerEndpointSpec;
import io.dropwizard.revolver.discovery.model.SimpleEndpointSpec;
Expand Down Expand Up @@ -402,6 +403,8 @@ public void run(T configuration, Environment environment) {

}

DegradeRegistry.getInstance();

environment.jersey().register(new RevolverRequestFilter(revolverConfig));

environment.jersey().register(
Expand Down
326 changes: 166 additions & 160 deletions src/main/java/io/dropwizard/revolver/core/util/RevolverCommandHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,177 +36,183 @@
import io.dropwizard.revolver.core.config.hystrix.ThreadPoolConfig;
import io.dropwizard.revolver.core.model.RevolverRequest;
import io.dropwizard.revolver.core.tracing.TraceInfo;
import io.dropwizard.revolver.degrade.DegradeRegistry;
import org.apache.commons.lang3.StringUtils;

import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;

/**
* @author phaneesh
*/
public class RevolverCommandHelper {

public static String getName(RevolverRequest request) {
return Joiner.on(".").join(request.getService(), request.getApi());
public static String getName(RevolverRequest request) {
return Joiner.on(".").join(request.getService(), request.getApi());
}

public static <T extends RevolverRequest> T normalize(T request) {
if (null == request) {
throw new RevolverExecutionException(RevolverExecutionException.Type.BAD_REQUEST,
"Request cannot be null");
}
TraceInfo traceInfo = request.getTrace();
if (traceInfo == null) {
traceInfo = new TraceInfo();
request.setTrace(traceInfo);
}
if (Strings.isNullOrEmpty(traceInfo.getRequestId())) {
throw new RevolverExecutionException(RevolverExecutionException.Type.BAD_REQUEST,
"Request ID must be passed in span");
}
if (Strings.isNullOrEmpty(traceInfo.getTransactionId())) {
throw new RevolverExecutionException(RevolverExecutionException.Type.BAD_REQUEST,
"Transaction ID must be passed");
}
if (0L == traceInfo.getTimestamp()) {
traceInfo.setTimestamp(System.currentTimeMillis());
}
return request;
}

/*
Group thread pools can be specified at service level. Different api of the service can subscribe to
different group thread pool
Timeout would be overridden if provided at individual api level
*/
public static HystrixCommand.Setter setter(RevolverCommand commandHandler,
String api) {
RuntimeConfig runtimeConfig = commandHandler.getRuntimeConfig();
RevolverServiceConfig serviceConfiguration = commandHandler.getServiceConfiguration();
CommandHandlerConfig config = commandHandler.getApiConfiguration();
CircuitBreakerConfig circuitBreakerConfig;
if (null != runtimeConfig) {
circuitBreakerConfig = runtimeConfig.getCircuitBreaker();
} else if (null != config.getRuntime() && null != config.getRuntime().getCircuitBreaker()) {
circuitBreakerConfig = config.getRuntime().getCircuitBreaker();
} else if (null != serviceConfiguration.getRuntime() && null != serviceConfiguration
.getRuntime().getCircuitBreaker()) {
circuitBreakerConfig = serviceConfiguration.getRuntime().getCircuitBreaker();
} else {
circuitBreakerConfig = new CircuitBreakerConfig();
}
ThreadPoolConfig serviceThreadPoolConfig = null;
if (null != serviceConfiguration.getRuntime() && null != serviceConfiguration.getRuntime()
.getThreadPool()) {
serviceThreadPoolConfig = serviceConfiguration.getRuntime().getThreadPool();
}
String keyName = StringUtils.EMPTY;

MetricsConfig metricsConfig;
if (null != runtimeConfig) {
metricsConfig = runtimeConfig.getMetrics();
} else {
metricsConfig = new MetricsConfig();
}

public static <T extends RevolverRequest> T normalize(T request) {
if (null == request) {
throw new RevolverExecutionException(RevolverExecutionException.Type.BAD_REQUEST,
"Request cannot be null");
}
TraceInfo traceInfo = request.getTrace();
if (traceInfo == null) {
traceInfo = new TraceInfo();
request.setTrace(traceInfo);
}
if (Strings.isNullOrEmpty(traceInfo.getRequestId())) {
throw new RevolverExecutionException(RevolverExecutionException.Type.BAD_REQUEST,
"Request ID must be passed in span");
}
if (Strings.isNullOrEmpty(traceInfo.getTransactionId())) {
throw new RevolverExecutionException(RevolverExecutionException.Type.BAD_REQUEST,
"Transaction ID must be passed");
}
if (0L == traceInfo.getTimestamp()) {
traceInfo.setTimestamp(System.currentTimeMillis());
}
return request;
Map<String, ThreadPoolConfig> threadPoolConfigMap;
if (null != serviceConfiguration.getThreadPoolGroupConfig() && null != serviceConfiguration
.getThreadPoolGroupConfig().getThreadPools()) {
threadPoolConfigMap = serviceConfiguration.getThreadPoolGroupConfig().getThreadPools()
.stream()
.collect(Collectors.toMap(ThreadPoolConfig::getThreadPoolName, t -> t));
} else {
threadPoolConfigMap = Maps.newHashMap();
}

/*
Group thread pools can be specified at service level. Different api of the service can subscribe to
different group thread pool
Timeout would be overridden if provided at individual api level
*/
public static HystrixCommand.Setter setter(RevolverCommand commandHandler,
String api) {
RuntimeConfig runtimeConfig = commandHandler.getRuntimeConfig();
RevolverServiceConfig serviceConfiguration = commandHandler.getServiceConfiguration();
CommandHandlerConfig config = commandHandler.getApiConfiguration();
CircuitBreakerConfig circuitBreakerConfig;
if (null != runtimeConfig) {
circuitBreakerConfig = runtimeConfig.getCircuitBreaker();
} else if (null != config.getRuntime() && null != config.getRuntime().getCircuitBreaker()) {
circuitBreakerConfig = config.getRuntime().getCircuitBreaker();
} else if (null != serviceConfiguration.getRuntime() && null != serviceConfiguration
.getRuntime().getCircuitBreaker()) {
circuitBreakerConfig = serviceConfiguration.getRuntime().getCircuitBreaker();
} else {
circuitBreakerConfig = new CircuitBreakerConfig();
}
ThreadPoolConfig serviceThreadPoolConfig = null;
if (null != serviceConfiguration.getRuntime() && null != serviceConfiguration.getRuntime()
.getThreadPool()) {
serviceThreadPoolConfig = serviceConfiguration.getRuntime().getThreadPool();
}
String keyName = StringUtils.EMPTY;

MetricsConfig metricsConfig;
if (null != runtimeConfig) {
metricsConfig = runtimeConfig.getMetrics();
} else {
metricsConfig = new MetricsConfig();
}

Map<String, ThreadPoolConfig> threadPoolConfigMap;
if (null != serviceConfiguration.getThreadPoolGroupConfig() && null != serviceConfiguration
.getThreadPoolGroupConfig().getThreadPools()) {
threadPoolConfigMap = serviceConfiguration.getThreadPoolGroupConfig().getThreadPools()
.stream()
.collect(Collectors.toMap(ThreadPoolConfig::getThreadPoolName, t -> t));
} else {
threadPoolConfigMap = Maps.newHashMap();
}

ThreadPoolConfig threadPoolConfig;

if (null != config.getRuntime() && null != config.getRuntime().getThreadPool()
&& StringUtils.isNotEmpty(config.getRuntime().getThreadPool().getThreadPoolName())
&& null != threadPoolConfigMap
.get(config.getRuntime().getThreadPool().getThreadPoolName())) {

threadPoolConfig = threadPoolConfigMap
.get(config.getRuntime().getThreadPool().getThreadPoolName());
keyName = threadPoolConfig.getThreadPoolName();

} else if (config.isSharedPool() && null != serviceThreadPoolConfig) {

threadPoolConfig = serviceThreadPoolConfig;
if (StringUtils.isEmpty(keyName)) {
keyName = Joiner.on(".")
.join(commandHandler.getServiceConfiguration().getService(), "shared");
}

} else if (null != config.getRuntime() && null != config.getRuntime().getThreadPool()) {

threadPoolConfig = config.getRuntime().getThreadPool();
keyName = Joiner.on(".")
.join(commandHandler.getServiceConfiguration().getService(), api);

} else if (null != serviceThreadPoolConfig) {
threadPoolConfig = serviceConfiguration.getRuntime().getThreadPool();
if (StringUtils.isEmpty(keyName)) {
keyName = Joiner.on(".")
.join(commandHandler.getServiceConfiguration().getService(), api);
}

} else if (null != runtimeConfig) {
threadPoolConfig = runtimeConfig.getThreadPool();
keyName = Joiner.on(".")
.join(commandHandler.getServiceConfiguration().getService(), api);

} else {
threadPoolConfig = new ThreadPoolConfig();
keyName = Joiner.on(".")
.join(commandHandler.getServiceConfiguration().getService(), api);
}

//Setting timeout from api thread pool config
if (null != config.getRuntime() && null != config.getRuntime().getThreadPool()) {
threadPoolConfig.setTimeout(config.getRuntime().getThreadPool().getTimeout());
}

int concurrency = threadPoolConfig.getConcurrency();
int coreSize = (int) Math.ceil(concurrency * metricsConfig.getCorePoolSizeReductionParam());
return HystrixCommand.Setter.withGroupKey(
HystrixCommandGroupKey.Factory.asKey(serviceConfiguration.getService()))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withExecutionIsolationStrategy(threadPoolConfig.isSemaphoreIsolated()
? HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE
: HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
.withExecutionIsolationSemaphoreMaxConcurrentRequests(
threadPoolConfig.getConcurrency())
.withFallbackIsolationSemaphoreMaxConcurrentRequests(
threadPoolConfig.getConcurrency())
.withFallbackEnabled(commandHandler.isFallbackEnabled())
.withCircuitBreakerErrorThresholdPercentage(
circuitBreakerConfig.getErrorThresholdPercentage())
.withCircuitBreakerRequestVolumeThreshold(
circuitBreakerConfig.getNumAcceptableFailuresInTimeWindow())
.withCircuitBreakerSleepWindowInMilliseconds(
circuitBreakerConfig.getWaitTimeBeforeRetry())
.withExecutionTimeoutInMilliseconds(threadPoolConfig.getTimeout())
.withMetricsHealthSnapshotIntervalInMilliseconds(
metricsConfig.getHealthCheckInterval())
.withMetricsRollingPercentileBucketSize(
metricsConfig.getPercentileBucketSize())
.withMetricsRollingPercentileWindowInMilliseconds(
metricsConfig.getPercentileTimeInMillis())).andCommandKey(
HystrixCommandKey.Factory.asKey(Joiner.on(".")
.join(commandHandler.getServiceConfiguration().getService(), api)))
.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(keyName))
.andThreadPoolPropertiesDefaults(
HystrixThreadPoolProperties.Setter().withCoreSize(coreSize)
.withMaxQueueSize(threadPoolConfig.getMaxRequestQueueSize())
.withMaximumSize(concurrency)
.withKeepAliveTimeMinutes(
threadPoolConfig.getKeepAliveTimeInMinutes())
.withQueueSizeRejectionThreshold(
threadPoolConfig.getDynamicRequestQueueSize())
.withAllowMaximumSizeToDivergeFromCoreSize(true)
.withMetricsRollingStatisticalWindowBuckets(
metricsConfig.getStatsBucketSize())
.withMetricsRollingStatisticalWindowInMilliseconds(
metricsConfig.getStatsTimeInMillis()));
ThreadPoolConfig threadPoolConfig;

if (null != config.getRuntime() && null != config.getRuntime().getThreadPool()
&& StringUtils.isNotEmpty(config.getRuntime().getThreadPool().getThreadPoolName())
&& null != threadPoolConfigMap
.get(config.getRuntime().getThreadPool().getThreadPoolName())) {

threadPoolConfig = threadPoolConfigMap
.get(config.getRuntime().getThreadPool().getThreadPoolName());
keyName = threadPoolConfig.getThreadPoolName();

} else if (config.isSharedPool() && null != serviceThreadPoolConfig) {

threadPoolConfig = serviceThreadPoolConfig;
if (StringUtils.isEmpty(keyName)) {
keyName = Joiner.on(".")
.join(commandHandler.getServiceConfiguration().getService(), "shared");
}

} else if (null != config.getRuntime() && null != config.getRuntime().getThreadPool()) {

threadPoolConfig = config.getRuntime().getThreadPool();
keyName = Joiner.on(".")
.join(commandHandler.getServiceConfiguration().getService(), api);

} else if (null != serviceThreadPoolConfig) {
threadPoolConfig = serviceConfiguration.getRuntime().getThreadPool();
if (StringUtils.isEmpty(keyName)) {
keyName = Joiner.on(".")
.join(commandHandler.getServiceConfiguration().getService(), api);
}

} else if (null != runtimeConfig) {
threadPoolConfig = runtimeConfig.getThreadPool();
keyName = Joiner.on(".")
.join(commandHandler.getServiceConfiguration().getService(), api);

} else {
threadPoolConfig = new ThreadPoolConfig();
keyName = Joiner.on(".")
.join(commandHandler.getServiceConfiguration().getService(), api);
}

//Setting timeout from api thread pool config
if (null != config.getRuntime() && null != config.getRuntime().getThreadPool()) {
threadPoolConfig.setTimeout(config.getRuntime().getThreadPool().getTimeout());
}

final String hystrixCommandKey = Joiner.on(".")
.join(commandHandler.getServiceConfiguration().getService(), api);
int concurrency = DegradeRegistry.getInstance().getDegradedThreadPool(hystrixCommandKey,
threadPoolConfig.getConcurrency());
int timeout = DegradeRegistry.getInstance().getDegradedTimeout(hystrixCommandKey,
threadPoolConfig.getTimeout());
int coreSize = (int) Math.ceil(concurrency * metricsConfig.getCorePoolSizeReductionParam());
return HystrixCommand.Setter.withGroupKey(
HystrixCommandGroupKey.Factory.asKey(serviceConfiguration.getService()))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withExecutionIsolationStrategy(threadPoolConfig.isSemaphoreIsolated()
? HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE
: HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
.withExecutionIsolationSemaphoreMaxConcurrentRequests(
threadPoolConfig.getConcurrency())
.withFallbackIsolationSemaphoreMaxConcurrentRequests(
threadPoolConfig.getConcurrency())
.withFallbackEnabled(commandHandler.isFallbackEnabled())
.withCircuitBreakerErrorThresholdPercentage(
circuitBreakerConfig.getErrorThresholdPercentage())
.withCircuitBreakerRequestVolumeThreshold(
circuitBreakerConfig.getNumAcceptableFailuresInTimeWindow())
.withCircuitBreakerSleepWindowInMilliseconds(
circuitBreakerConfig.getWaitTimeBeforeRetry())
.withExecutionTimeoutInMilliseconds(timeout)
.withMetricsHealthSnapshotIntervalInMilliseconds(
metricsConfig.getHealthCheckInterval())
.withMetricsRollingPercentileBucketSize(
metricsConfig.getPercentileBucketSize())
.withMetricsRollingPercentileWindowInMilliseconds(
metricsConfig.getPercentileTimeInMillis())).andCommandKey(
HystrixCommandKey.Factory.asKey(hystrixCommandKey))
.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(keyName))
.andThreadPoolPropertiesDefaults(
HystrixThreadPoolProperties.Setter().withCoreSize(coreSize)
.withMaxQueueSize(threadPoolConfig.getMaxRequestQueueSize())
.withMaximumSize(concurrency)
.withKeepAliveTimeMinutes(
threadPoolConfig.getKeepAliveTimeInMinutes())
.withQueueSizeRejectionThreshold(
threadPoolConfig.getDynamicRequestQueueSize())
.withAllowMaximumSizeToDivergeFromCoreSize(true)
.withMetricsRollingStatisticalWindowBuckets(
metricsConfig.getStatsBucketSize())
.withMetricsRollingStatisticalWindowInMilliseconds(
metricsConfig.getStatsTimeInMillis()));
}
}
Loading