Я пытаюсь настроить поведение HystrixCommand следующим образом:
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)));
}
}
Я ожидаю, что произойдет короткое замыкание входящих команд после того, как только одно исключение (или тайм-аут) произойдет в течение следующих 10secs (sleepwindowinmilis).
Чтобы проверить это, у меня есть следующий модульный тест.
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);
}
}
}
Но метод isCircuitBreakerOpen () возвращает false в исключении testSimpleUnsuccessfulExecutionBecauseException и testSimpleUnsuccessfulExecutionBec.1009 *
Может ли кто-нибудь вести меня по правильному пути?Спасибо.