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

Added supports for setting threadPoolProperties through @HystrixCommand annotation #326

Merged
merged 5 commits into from
Nov 9, 2014
Merged
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
19 changes: 19 additions & 0 deletions hystrix-contrib/hystrix-javanica/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,25 @@ ConfigurationManager.getConfigInstance().setProperty("hystrix.command.getUserByI
```
More about Hystrix command properties [command](https://github.com/Netflix/Hystrix/wiki/Configuration#wiki-CommandExecution) and [fallback](https://github.com/Netflix/Hystrix/wiki/Configuration#wiki-CommandFallback)

ThreadPoolProperties can be set using @HystrixCommand's 'threadPoolProperties' like below:

```java
@HystrixCommand(commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "500")
},
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "30"),
@HystrixProperty(name = "maxQueueSize", value = "101"),
@HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "15"),
@HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "12"),
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "1440")
})
public User getUserById(String id) {
return userResource.getUserById(id);
}
```

## Hystrix collapser

Suppose you have some command which calls should be collapsed in one backend call. For this goal you can use ```@HystrixCollapser``` annotation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@
*/
HystrixProperty[] commandProperties() default {};

/**
* Specifies thread pool properties.
*
* @return thread pool properties
*/
HystrixProperty[] threadPoolProperties() default {};

/**
* Defines exceptions which should be ignored and wrapped to throw in HystrixBadRequestException.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@

import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import com.netflix.config.ConfigurationManager;
import com.netflix.hystrix.HystrixCollapser;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;

Expand Down Expand Up @@ -51,6 +54,8 @@ public T create(MetaHolder metaHolder,
metaHolder.getHystrixCommand().commandKey()
: metaHolder.getDefaultCommandKey();

HystrixPropertiesManager.initializeThreadPoolProperties(metaHolder.getHystrixCommand());

CommandSetterBuilder setterBuilder = new CommandSetterBuilder();
setterBuilder.commandKey(commandKey);
setterBuilder.groupKey(groupKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixThreadPoolKey;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import org.apache.commons.lang3.StringUtils;

/**
Expand All @@ -29,6 +30,7 @@ public class CommandSetterBuilder {
private String groupKey;
private String commandKey;
private String threadPoolKey;
private HystrixThreadPoolProperties.Setter threadPoolProperties = null;

public CommandSetterBuilder groupKey(String pGroupKey) {
this.groupKey = pGroupKey;
Expand All @@ -50,11 +52,15 @@ public CommandSetterBuilder commandKey(String pCommandKey, String def) {
return this;
}

public CommandSetterBuilder threadPoolProperties(HystrixThreadPoolProperties.Setter threadPoolProperties) {
this.threadPoolProperties = threadPoolProperties;
return this;
}

public CommandSetterBuilder threadPoolKey(String pThreadPoolKey) {
this.threadPoolKey = pThreadPoolKey;
return this;
}

/**
* Creates instance of {@link HystrixCommand.Setter}.
*
Expand All @@ -67,6 +73,9 @@ public HystrixCommand.Setter build() {
if (StringUtils.isNotBlank(threadPoolKey)) {
setter.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(threadPoolKey));
}
if (threadPoolProperties != null) {
setter.andThreadPoolPropertiesDefaults(threadPoolProperties);
}
return setter;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import com.google.common.collect.Maps;
import com.netflix.config.ConfigurationManager;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
Expand Down Expand Up @@ -96,4 +97,22 @@ private static void validate(HystrixProperty hystrixProperty) throws IllegalArgu
Validate.notBlank(hystrixProperty.name(), "hystrix property name cannot be null");
}

public static void initializeThreadPoolProperties(HystrixCommand hystrixCommand) {
if(hystrixCommand.threadPoolProperties() == null || hystrixCommand.threadPoolProperties().length == 0) {
return;
}

HystrixThreadPoolProperties.Setter setter = HystrixThreadPoolProperties.Setter();
String threadPoolKey = hystrixCommand.threadPoolKey();
if(threadPoolKey == null || "".equals(threadPoolKey)) {
threadPoolKey = "default";
}

HystrixProperty[] properties = hystrixCommand.threadPoolProperties();
for(HystrixProperty property : properties) {
String name = String.format("hystrix.threadpool.%s.%s", threadPoolKey, property.name());
ConfigurationManager.getConfigInstance().setProperty(name, property.value());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

import com.netflix.hystrix.HystrixEventType;
import com.netflix.hystrix.HystrixRequestLog;
import com.netflix.hystrix.HystrixThreadPool;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.hystrix.contrib.javanica.test.spring.conf.AopCglibConfig;
import com.netflix.hystrix.contrib.javanica.test.spring.domain.User;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -15,6 +18,9 @@
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.lang.reflect.Field;
import java.util.concurrent.TimeUnit;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

Expand All @@ -26,7 +32,7 @@ public class CommandPropertiesTest {
private UserService userService;

@Test
public void testGetUser() {
public void testGetUser() throws NoSuchFieldException, IllegalAccessException {
HystrixRequestContext context = HystrixRequestContext.initializeContext();
try {
User u1 = userService.getUser("1", "name: ");
Expand All @@ -41,6 +47,21 @@ public void testGetUser() {
// assert properties
assertEquals(110, command.getProperties().executionIsolationThreadTimeoutInMilliseconds().get().intValue());
assertEquals(false, command.getProperties().executionIsolationThreadInterruptOnTimeout().get());

Field field = command.getClass().getSuperclass().getSuperclass().getSuperclass().getDeclaredField("threadPool");
field.setAccessible(true);
HystrixThreadPool threadPool = (HystrixThreadPool) field.get(command);

Field field2 = HystrixThreadPool.HystrixThreadPoolDefault.class.getDeclaredField("properties");
field2.setAccessible(true);
HystrixThreadPoolProperties properties = (HystrixThreadPoolProperties) field2.get(threadPool);

assertEquals(30, (int) properties.coreSize().get());
assertEquals(101, (int) properties.maxQueueSize().get());
assertEquals(2, (int) properties.keepAliveTimeMinutes().get());
assertEquals(15, (int) properties.queueSizeRejectionThreshold().get());
assertEquals(1440, (int) properties.metricsRollingStatisticalWindowInMilliseconds().get());
assertEquals(12, (int) properties.metricsRollingStatisticalWindowBuckets().get());
} finally {
context.shutdown();
}
Expand Down Expand Up @@ -70,6 +91,14 @@ public static class UserService {
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "110"),
@HystrixProperty(name = "execution.isolation.thread.interruptOnTimeout", value = "false")
},
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "30"),
@HystrixProperty(name = "maxQueueSize", value = "101"),
@HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
@HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "12"),
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "15"),
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "1440")
})
public User getUser(String id, String name) {
return new User(id, name + id); // it should be network call
Expand Down