乌龙!Hystrix命令执行超时!
我在使用hystrix编写一个模拟命令执行超时的demo。
1 import com.netflix.hystrix.*; 2 import lombok.extern.slf4j.Slf4j; 3 4 @Slf4j 5 public class HystrixTimeoutDemo { 6 7 static class TestCommand extends HystrixCommand<String> { 8 String param; 9 10 protected TestCommand(String param) { 11 super(HystrixCommand.Setter 12 .withGroupKey(HystrixCommandGroupKey.Factory.asKey("TestCommand")) 13 .andCommandPropertiesDefaults(HystrixCommandProperties.Setter() 14 .withExecutionTimeoutInMilliseconds(5000) 15 ) 16 .andCommandPropertiesDefaults(HystrixCommandProperties.Setter() 17 .withCircuitBreakerEnabled(false) 18 // .withCircuitBreakerRequestVolumeThreshold(100) 19 // .withCircuitBreakerErrorThresholdPercentage(100) 20 // .withCircuitBreakerSleepWindowInMilliseconds(3000) 21 ) 22 ); 23 this.param = param; 24 } 25 26 @Override 27 protected String run() throws Exception { 28 log.info("{}--RUN start", param); 29 TimeUnit.MILLISECONDS.sleep(2000); 30 log.info("{}--RUN end-------------", param); 31 return param + "--正常返回 "; 32 } 33 34 @Override 35 protected String getFallback() { 36 return param + "--fallback(降级)"; 37 } 38 } 39 40 public static void main(String[] args) throws IOException { 41 log.info("{}", new TestCommand("command" + 1).execute()); 42 } 43 }
运行代码时,发现一个奇怪的现象。就是,我设置的 命令执行超时时间是 5s。 可是在命令的run方法里sleep了 2s,却提示执行超时了。
10:07:41.961 [hystrix-TestCommand-1] INFO com.serviceshare.HystrixTimeoutDemo - command1--RUN start
10:07:42.970 [main] INFO com.serviceshare.HystrixTimeoutDemo - command1--fallback(降级)
这不禁让我有些疑惑呢。
于是,在我翻查console控制台的log时,我发现了下面hystrix的属性初始化,它把commandExecutionTimeout设置成了默认的1s,这并不是我所期望的————应该是 5s 才对呀!
10:07:41.910 [main] DEBUG com.netflix.hystrix.strategy.properties.HystrixPropertiesChainedProperty - Flipping property: hystrix.command.TestCommand.execution.isolation.thread.timeoutInMilliseconds to use NEXT property: hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds = 1000
而后,再分析我的代码,我才意识到是我上面程序的失误。原来,是hystrix构造器的Setter里重复调用了 andCommandPropertiesDefaults,然后后者把前者覆盖了。改正代码后,一切运行正常。
... 10:17:17.301 [main] DEBUG com.netflix.hystrix.strategy.properties.HystrixPropertiesChainedProperty - Flipping property: hystrix.command.TestCommand.execution.isolation.thread.timeoutInMilliseconds to use its current value: 5000 ... 10:17:17.350 [hystrix-TestCommand-1] INFO com.serviceshare.HystrixTimeoutDemo - command1--RUN start 10:17:19.355 [hystrix-TestCommand-1] INFO com.serviceshare.HystrixTimeoutDemo - command1--RUN end------------- 10:17:19.360 [main] INFO com.serviceshare.HystrixTimeoutDemo - command1--正常返回
关于com.netflix.hystrix.HystrixCommand.Setter
HystrixCommand构造器需要groupKey(命令组键)、commandKey(命令键)、threadPoolKey(线程池键)、commandPropertiesDefaults(命令的属性默认设置)、threadPoolPropertiesDefaults(线程池的属性默认设置)等一系列参数,这在我们使用上会有些不便。而hystrix团队在HystrixCommand里定义了一个Setter内部类,它提供了一组基于链式调用方式的setter方法,可以让开发者更灵活、更流畅地为HystrixCommand构造器赋值。
贴出来它的源码,大家欣赏一下。
/** * Fluent interface for arguments to the {@link HystrixCommand} constructor. * <p> * The required arguments are set via the 'with' factory method and optional arguments via the 'and' chained methods. * <p> * Example: * <pre> {@code * Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GroupName")) .andCommandKey(HystrixCommandKey.Factory.asKey("CommandName")); * } </pre> * * @NotThreadSafe */ final public static class Setter { protected final HystrixCommandGroupKey groupKey; protected HystrixCommandKey commandKey; protected HystrixThreadPoolKey threadPoolKey; protected HystrixCommandProperties.Setter commandPropertiesDefaults; protected HystrixThreadPoolProperties.Setter threadPoolPropertiesDefaults; protected Setter(HystrixCommandGroupKey groupKey) { this.groupKey = groupKey; } public static Setter withGroupKey(HystrixCommandGroupKey groupKey) { return new Setter(groupKey); } public Setter andCommandKey(HystrixCommandKey commandKey) { this.commandKey = commandKey; return this; } public Setter andThreadPoolKey(HystrixThreadPoolKey threadPoolKey) { this.threadPoolKey = threadPoolKey; return this; } public Setter andCommandPropertiesDefaults(HystrixCommandProperties.Setter commandPropertiesDefaults) { this.commandPropertiesDefaults = commandPropertiesDefaults; return this; } public Setter andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter threadPoolPropertiesDefaults) { this.threadPoolPropertiesDefaults = threadPoolPropertiesDefaults; return this; } }
当看到一些不好的代码时,会发现我还算优秀;当看到优秀的代码时,也才意识到持续学习的重要!--buguge
本文来自博客园,转载请注明原文链接:https://www.cnblogs.com/buguge/p/18261298