java - Hystrix CircuitBreakerSleepWindowInMilliseconds 无法按预期工作

标签 java junit hystrix circuit-breaker

我正在测试 Hystrix CircuitBreaker 实现。命令类如下所示:

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)。为什么会发生这种情况?我做错了什么?

最佳答案

根据 Hystrix docs健康快照将每 500 毫秒拍摄一次(默认情况下)。这意味着在前 500 毫秒内 hystrix 发生的所有事情都不会影响断路器状态。在您的示例中,您获得了 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

关于java - Hystrix CircuitBreakerSleepWindowInMilliseconds 无法按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49692024/

相关文章:

java - 使用gson读取java中的json对象文件不断获取null

java - 将速度X和速度Y转换为角度

java - 在 Mockito.when 中多次使用相同的 ArgumentMatchers

java - Hystrix 执行模式

Java 二叉树 : How to balance a tree in the insert method?

具有 jetty 内存泄漏问题的java服务器

java - Ldap 单元测试模拟命名枚举

java - 错误 (23,17) 无法解析 junit :junit: 4. 12 @Android Studio v.2

http - 哪些 HTTP 错误不应该触发自动重试?

java - Hystrix 命令失败并显示 "timed-out and no fallback available"