【问题标题】:Hystrix CircuitBreakerSleepWindowInMilliseconds doesn't work as expectedHystrix CircuitBreakerSleepWindowInMilliseconds 无法按预期工作
【发布时间】:2018-09-16 10:28:50
【问题描述】:

我正在测试 Hystrix 断路器的实现。这是命令类的样子:

public class CommandOne extends HystrixCommand<String>
{
    private MyExternalService service;    
    public static int runCount = 0;

    public CommandGetPunterUnpayoutExternalBets(MyExternalServoce service)
    {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("AAA"))
                .andThreadPoolPropertiesDefaults(
                        HystrixThreadPoolProperties.Setter().
                         .withMetricsRollingStatisticalWindowInMilliseconds(10000))
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        .withCircuitBreakerEnabled(true)
                        .withCircuitBreakerErrorThresholdPercentage(20)
                        .withCircuitBreakerRequestVolumeThreshold(10)
                        .withExecutionTimeoutInMilliseconds(30)
                        .withCircuitBreakerSleepWindowInMilliseconds(100000)));

        this.service = service;
    }


    @Override
    protected String run()
    {
        run++;
        return service.callMethod();
    }


    @Override
    protected String getFallback()
    {
        return "default;
    }
}

命令是这样调用的:

public class AnotherClass
{
    private MyExternalServoce service; 

    public String callCmd()
    {
        CommandOne command = new CommandOne(service);
        return command.execute();
    }
}

在测试中我执行后续步骤:

@Test
    public void test()
{
    AnotherClass anotherClass = new AnotherClass();

    // stubbing exception on my service
    when(service.callMethod()).thenThrow(new RuntimeException());
    for (int i = 0; i < 1000; i++)
        {
             anotherClass.callCmd();
        }
    System.out.println("Run method was called times = " + CommandOne.runCount);
}

我对给定命令配置的期望:MyExternalService.callMethod() 应该被调用 10 次(RequestVolumeThreshold),之后不被调用 100000 毫秒(长时间)。在我的测试用例中,我希望 CommandOne.runCount = 10。 但实际上我收到了 150 到 200 次 MyExternalService.callMethod() (CommandOne.runCount = (150-200) 的调用。为什么会这样?我做错了什么?

【问题讨论】:

    标签: java junit hystrix circuit-breaker


    【解决方案1】:

    根据 Hystrix docs 健康快照将每 500 毫秒拍摄一次(默认情况下)。这意味着 hystrix 在前 500 毫秒内发生的一切都不会影响断路器状态。在您的示例中,您获得了 runCount 的随机值,因为每次您的机器每 500 毫秒执行一次请求的随机值,并且仅在该时间间隔电路状态更新和关闭之后。

    请看一个简化的例子:

     public class CommandOne extends HystrixCommand<String> {
    
        private String content;
        public static int runCount = 0;
    
    
        public CommandOne(String s) {
            super(Setter.withGroupKey
                    (HystrixCommandGroupKey.Factory.asKey("SnapshotIntervalTest"))
                    .andCommandPropertiesDefaults(
                            HystrixCommandProperties.Setter()
                                    .withCircuitBreakerSleepWindowInMilliseconds(500000)
                                    .withCircuitBreakerRequestVolumeThreshold(9)
                                    .withMetricsHealthSnapshotIntervalInMilliseconds(50)
                                    .withMetricsRollingStatisticalWindowInMilliseconds(100000)
                    )
            );
            this.content = s;
        }
    
        @Override
        public String run() throws Exception {
            Thread.sleep(100);
            runCount++;
            if ("".equals(content)) {
                throw new Exception();
            }
            return content;
        }
    
        @Override
        protected String getFallback() {
            return "FAILURE-" + content;
        }
    
    }
    
        @Test
        void test() {
    
            for (int i = 0; i < 100; i++) {
                CommandOne commandOne = new CommandOne();
                commandOne.execute();
            }
            Assertions.assertEquals(10, CommandOne.runCount);
        }
    

    在这个例子中我添加了:

    • withMetricsHealthSnapshotIntervalInMilliseconds(50) 允许 hystrix 每 50 毫秒拍摄一次快照。
    • Thread.sleep(100); 使请求变慢一点,没有它,它们会快 50 毫秒,我们将面临最初的问题。

    尽管进行了所有这些修改,但我还是看到了一些随机故障。在此之后,我得出结论,像这样测试 hystrix 不是一个好主意。我们可以使用它来代替它:

    1) Fallback/Success flow behavior by manually setting open/close circuit state.

    2)Configuration tests

    【讨论】:

      猜你喜欢
      • 2013-12-23
      • 2014-12-09
      • 2016-01-13
      • 2020-09-21
      • 2011-08-17
      • 2012-04-29
      • 2021-08-12
      • 2019-02-04
      • 2014-12-02
      相关资源
      最近更新 更多