首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Hystrix不是短路

Hystrix不是短路
EN

Stack Overflow用户
提问于 2018-12-27 17:06:35
回答 1查看 142关注 0票数 0

我尝试这样设置HystrixCommand的行为:

代码语言:javascript
复制
public abstract class AbstractCircuitBreakerCommand<E> extends HystrixCommand<E> {

    protected AbstractCircuitBreakerCommand(final String groupKey, final String commandKey) {

        this(groupKey, commandKey, TimeUnit.SECONDS, 10, TimeUnit.SECONDS, 3, TimeUnit.SECONDS, 10, 1);
    }

    protected AbstractCircuitBreakerCommand(
            final String groupKey, final String commandKey,
            final TimeUnit metricsWindowTimeUnit, final int metricsWindowTime,
            final TimeUnit timeoutTimeUnit, final int timeoutTime,
            final TimeUnit windowTimeUnit, final int windowTime,
            final int threshold) {

        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
                .andCommandKey(HystrixCommandKey.Factory.asKey(commandKey))
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
                        .withMetricsRollingStatisticalWindowInMilliseconds((int) metricsWindowTimeUnit.toMillis(metricsWindowTime))
                        .withExecutionTimeoutEnabled(true)
                        .withExecutionTimeoutInMilliseconds((int) timeoutTimeUnit.toMillis(timeoutTime))
                        .withCircuitBreakerEnabled(true)
                        .withCircuitBreakerRequestVolumeThreshold(threshold)
                        .withCircuitBreakerErrorThresholdPercentage(0)
                        .withCircuitBreakerSleepWindowInMilliseconds((int) windowTimeUnit.toMillis(windowTime))
                        .withFallbackEnabled(true)));
    }

}

我期望的是在接下来的10秒内只有一个异常(或超时)发生后,短路传入的命令。

为了测试它,我进行了下一个单元测试。

代码语言:javascript
复制
public class AbstractCircuitBreakerCommandTest {

    private final static int ERROR_VALUE = Integer.MIN_VALUE;

    private final static String GROUP_KEY = "GROUP_KEY";
    private final static String COMMAND_KEY = "COMMAND_KEY";

    @Test
    public void testSimpleExecution() {

        final int expectedValue = 1;

        final SimpleCircuitBreakerCommandToTest circuitBreakerCommand =
                new SimpleCircuitBreakerCommandToTest(GROUP_KEY, COMMAND_KEY, value -> expectedValue);

        Assert.assertEquals(expectedValue, (int) circuitBreakerCommand.execute());
        Assert.assertTrue(circuitBreakerCommand.isExecutionComplete());
        Assert.assertTrue(circuitBreakerCommand.isSuccessfulExecution());
    }

    @Test
    public void testSimpleUnsuccessfulExecutionBecauseException() {

        final SimpleCircuitBreakerCommandToTest circuitBreakerCommand =
                new SimpleCircuitBreakerCommandToTest(GROUP_KEY, COMMAND_KEY, value -> {

                    throw new Exception("Test");
                });

        Assert.assertEquals(ERROR_VALUE, (int) circuitBreakerCommand.execute());
        Assert.assertTrue(circuitBreakerCommand.isExecutionComplete());
        Assert.assertTrue(circuitBreakerCommand.isFailedExecution());
        Assert.assertTrue(circuitBreakerCommand.isCircuitBreakerOpen());
    }

    @Test
    public void testSimpleUnsuccessfulExecutionBecauseTimeout() {

        final SimpleCircuitBreakerCommandToTest circuitBreakerCommand =
                new SimpleCircuitBreakerCommandToTest(GROUP_KEY, COMMAND_KEY, value -> {

                    SleepHelper.sleep(TimeUnit.SECONDS, 4); // The default value is -> 3 seconds.

                    return 1;
                });

        Assert.assertEquals(ERROR_VALUE, (int) circuitBreakerCommand.execute());
        Assert.assertTrue(circuitBreakerCommand.isExecutionComplete());
        Assert.assertTrue(circuitBreakerCommand.isFailedExecution());
        Assert.assertTrue(circuitBreakerCommand.isCircuitBreakerOpen());
    }

    private static abstract class AbstractCircuitBreakerCommandToTest extends AbstractCircuitBreakerCommand<Integer> {

        private final Integer value;
        private final TestAction testAction;

        protected AbstractCircuitBreakerCommandToTest(
                final String groupKey, final String commandKey,
                final TestAction testAction) {

            this(groupKey, commandKey, 1, testAction);
        }

        protected AbstractCircuitBreakerCommandToTest(
                final String groupKey, final String commandKey,
                final Integer value, final TestAction testAction) {

            super(groupKey, commandKey);

            this.value = value;
            this.testAction = testAction;
        }

        @Override
        protected Integer run() throws Exception {

            return this.testAction.run(this.value);
        }

        @Override
        protected Integer getFallback() {

            return ERROR_VALUE;
        }

        @FunctionalInterface
        interface TestAction {

            Integer run(final Integer integer) throws Exception;

        }

    }

    private static class SimpleCircuitBreakerCommandToTest extends AbstractCircuitBreakerCommandToTest {

        protected SimpleCircuitBreakerCommandToTest(
                final String groupKey, final String commandKey,
                final TestAction testAction) {

            super(groupKey, commandKey, testAction);
        }

    }

} 

但是在testSimpleUnsuccessfulExecutionBecauseTimeout和testSimpleUnsuccessfulExecutionBecauseTimeout测试中,isCircuitBreakerOpen()方法返回false。

谁能指引我走正确的路?谢谢。

EN

回答 1

Stack Overflow用户

发布于 2019-01-03 02:26:17

这些测试中有一些错误,这里是修复的版本。

代码语言:javascript
复制
public class AbstractCircuitBreakerCommandTest {

    private final static int WAIT_WORK_DONE_IN_MS = 800;
    private final static int ERROR_VALUE = Integer.MIN_VALUE;

    private final static String GROUP_KEY = "GROUP_KEY";
    private final static String COMMAND_KEY = "COMMAND_KEY";

    @Test
    public void testSimpleExecution() {

        final int expectedValue = 1;

        final HystrixCommand circuitBreakerCommand =
                new SimpleCircuitBreakerCommandToTest(GROUP_KEY + "_0", COMMAND_KEY + "_0", value -> value);

        Assert.assertEquals(expectedValue, (int) circuitBreakerCommand.execute());
        Assert.assertTrue(circuitBreakerCommand.isExecutionComplete());
        Assert.assertTrue(circuitBreakerCommand.isSuccessfulExecution());
    }

    @Test
    public void testSimpleUnsuccessfulExecutionBecauseException() {

        final HystrixCommand circuitBreakerCommand =
                new SimpleCircuitBreakerCommandToTest(GROUP_KEY + "_1", COMMAND_KEY + "_1", value -> {

                    throw new Exception("Test");
                });

        Assert.assertEquals(ERROR_VALUE, (int) circuitBreakerCommand.execute());

        SleepHelper.sleep(TimeUnit.MILLISECONDS, WAIT_WORK_DONE_IN_MS);

        Assert.assertTrue(circuitBreakerCommand.isExecutionComplete());
        Assert.assertTrue(circuitBreakerCommand.isFailedExecution());
        Assert.assertTrue(circuitBreakerCommand.isCircuitBreakerOpen());
    }

    @Test
    public void testSimpleUnsuccessfulExecutionBecauseTimeout() {

        final HystrixCommand circuitBreakerCommand =
                new SimpleCircuitBreakerCommandToTest(GROUP_KEY + "_2", COMMAND_KEY + "_2", value -> {

                    SleepHelper.sleep(TimeUnit.SECONDS, 4); // The default value is -> 3 seconds.

                    return value;
                });

        Assert.assertEquals(ERROR_VALUE, (int) circuitBreakerCommand.execute());

        SleepHelper.sleep(TimeUnit.MILLISECONDS, WAIT_WORK_DONE_IN_MS);

        Assert.assertTrue(circuitBreakerCommand.isExecutionComplete());
        Assert.assertTrue(circuitBreakerCommand.isResponseTimedOut());
        Assert.assertTrue(circuitBreakerCommand.isCircuitBreakerOpen());
    }

    private static abstract class AbstractCircuitBreakerCommandToTest extends AbstractCircuitBreakerCommand<Integer> {

        private final Integer value;
        private final TestAction testAction;

        protected AbstractCircuitBreakerCommandToTest(
                final String groupKey, final String commandKey,
                final TestAction testAction) {

            this(groupKey, commandKey, 1, testAction);
        }

        protected AbstractCircuitBreakerCommandToTest(
                final String groupKey, final String commandKey,
                final Integer value, final TestAction testAction) {

            super(groupKey, commandKey);

            this.value = value;
            this.testAction = testAction;
        }

        @Override
        protected Integer run() throws Exception {

            return this.testAction.run(this.value);
        }

        @Override
        protected Integer getFallback() {

            return ERROR_VALUE;
        }

        @FunctionalInterface
        interface TestAction {

            Integer run(final Integer integer) throws Exception;

        }

    }

    private static class SimpleCircuitBreakerCommandToTest extends AbstractCircuitBreakerCommandToTest {

        protected SimpleCircuitBreakerCommandToTest(
                final String groupKey, final String commandKey,
                final TestAction testAction) {

            super(groupKey, commandKey, testAction);
        }

    }

}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53942421

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档