Java Hystrix断路器LEEPWINDOWINDOWN';I don’我没有按预期工作

Java Hystrix断路器LEEPWINDOWINDOWN';I don’我没有按预期工作,java,junit,hystrix,circuit-breaker,Java,Junit,Hystrix,Circuit Breaker,我正在测试Hystrix断路器的实现。这是命令类的外观: public class CommandOne extends HystrixCommand<String> { private MyExternalService service; public static int runCount = 0; public CommandGetPunterUnpayoutExternalBets(MyExternalServoce service)

我正在测试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;
    }
}
在测试中,我将执行以下步骤:

@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);
}
@测试
公开无效测试()
{
AnotherClass AnotherClass=新的AnotherClass();
//我的服务上的存根异常
when(service.callMethod()).thenthow(newruntimeexception());
对于(int i=0;i<1000;i++)
{
另一个类:callCmd();
}
System.out.println(“调用运行方法的次数=”+CommandOne.runCount);
}
我对给定命令的配置所期望的是:MyExternalService.callMethod()应该被调用10次(RequestVolumeThreshold),之后就不会被调用100000毫秒(长时间)。在我的测试用例中,我希望CommandOne.runCount=10。 但事实上,我收到的MyExternalService.callMethod()(CommandOne.runCount=(150-200)调用次数从150到200次。为什么会发生这种情况?我做错了什么?

根据Hystrix,健康快照将每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);
    }
公共类CommandOne扩展了HystrixCommand{
私有字符串内容;
公共静态int运行计数=0;
公共命令一(字符串s){
超级(Setter.withGroupKey)
(HystrixCommandGroupKey.Factory.asKey(“快照间隔测试”))
.AND命令属性默认值(
HystrixCommandProperties.Setter()
.WithCircuitBreakerSleepWindows毫秒(500000)
.withCircuitBreakerRequestVolumeThreshold(9)
.WithMetricsHealthSnapshot间隔百万秒(50)
.WithMetricsRollingStatisticalWindows毫秒(100000)
)
);
此.content=s;
}
@凌驾
公共字符串run()引发异常{
睡眠(100);
运行计数++;
如果(“.”等于(内容)){
抛出新异常();
}
返回内容;
}
@凌驾
受保护的字符串getFallback(){
返回“失败-”+内容;
}
}
@试验
无效测试(){
对于(int i=0;i<100;i++){
CommandOne CommandOne=新CommandOne();
commandOne.execute();
}
assertEquals(10,CommandOne.runCount);
}
在本例中,我添加了:

  • 使用MetricsHealthSnapshot IntervalinMills(50)
    允许hystrix每50毫秒拍摄一次快照
  • Thread.sleep(100);
    要使请求稍微慢一点,如果没有它,请求速度将快于50毫秒,我们将面临初始问题
尽管进行了所有这些修改,我还是看到了一些随机故障。在此之后,我得出结论,像这样测试hystrix不是一个好主意。我们可以使用:

1)

(二)

 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);
    }