buguge - Keep it simple,stupid

知识就是力量,但更重要的,是运用知识的能力why buguge?

导航

乌龙!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 }
View Code

运行代码时,发现一个奇怪的现象。就是,我设置的 命令执行超时时间是 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;
    }
}

 

posted on 2024-06-21 20:29  buguge  阅读(37)  评论(0编辑  收藏  举报