我正在尝试将重试策略与CircuitBreaker模式与Failsafe结合使用,但是当尝试打开电路并且它被中断时,我得到一个CircuitBreakerOpenException异常。
https://github.com/jhalterman/failsafe
通过设置重试延迟小于电路的关闭时间来产生问题。
如何控制此异常以便不中断重试策略?我想这样做,因为我可以有多个同时实例向休息服务发起请求,并且重试不会中断。
我的代码:
public class UnstableApplication {
private final int MAX_FAILS = 4;
private AtomicInteger failCount = new AtomicInteger(1);
public String generateId() throws Exception {
if (failCount.getAndIncrement() < MAX_FAILS) {
System.err.printf("UnstableApplication throws SampleException at '%s'\n", ZonedDateTime.now());
throw new Exception();
}
final String id = UUID.randomUUID().toString();
System.out.printf("UnstableApplication: id '%s' generated at '%s'\n", id, ZonedDateTime.now());
return id;
}
}
public class FailsafeExample {
public static void main(String[] args) throws Exception {
UnstableApplication app = new UnstableApplication();
RetryPolicy retryPolicy = new RetryPolicy()
.retryOn(Exception.class)
.withDelay(2, TimeUnit.SECONDS)
.withMaxRetries(5);
CircuitBreaker breaker = new CircuitBreaker();
breaker.withFailureThreshold(2);
breaker.withDelay(5, TimeUnit.SECONDS);
breaker.withSuccessThreshold(3);
breaker.onOpen(() -> {
System.out.println("Circuit breaker is open");
});
breaker.onClose(() -> {
System.out.println("Circuit breaker is close");
});
breaker.onHalfOpen(() -> {
System.out.println("Circuit breaker is half-close");
});
Failsafe.with(retryPolicy)
.with(breaker)
.onFailedAttempt((a, b) -> {
System.out.println(
String.format("Failed with exception: %s, at %s, circuit-breaker state is: %s",
b, ZonedDateTime.now(), breaker.getState()));
})
.onSuccess(cxn -> {
System.out.println("Succcess!");
})
.onFailure(cxn -> {
System.out.println("Failed!");
})
.get(new Callable<String>() {
@Override
public String call() throws Exception {
return app.generateId();
}
});
}
}
我的结果:
UnstableApplication throws SampleException at '2019-05-31T16:30:09.214Z[Etc/UTC]'
Failed with exception: java.lang.Exception, at 2019-05-31T16:30:09.221Z[Etc/UTC], circuit-breaker state is: CLOSED
UnstableApplication throws SampleException at '2019-05-31T16:30:11.229Z[Etc/UTC]'
Circuit breaker is open
Failed with exception: java.lang.Exception, at 2019-05-31T16:30:11.230Z[Etc/UTC], circuit-breaker state is: OPEN
Exception in thread "main" net.jodah.failsafe.CircuitBreakerOpenException
at net.jodah.failsafe.SyncFailsafe.call(SyncFailsafe.java:136)
at net.jodah.failsafe.SyncFailsafe.get(SyncFailsafe.java:56)
at com.kash.test.Foo.main(Foo.java:63)
答案 0 :(得分:1)
在此示例中,当我尝试将Circuit Breaker与Retry Policy结合使用时,我的理解是这样的:
CircuitBreaker breaker = new CircuitBreaker()
.withFailureThreshold(3, 10)
.withSuccessThreshold(5)
.failOn(Exception.class)
.withDelay(30, TimeUnit.SECONDS);
RetryPolicy retryPolicy = new RetryPolicy()
.retryOn(ConnectException.class)
.withDelay(3, TimeUnit.SECONDS)
.withMaxRetries(5);
答案 1 :(得分:1)
这是预期的行为。当电路断开时,到该端点的请求将停止-如果依赖关系中断或不可靠,当然还必须切断重试,否则您将像经历重试一样容易地遇到大量重试。根本没有cb。
如果您想继续发送请求,可能是因为断开电路的触发信号过于敏感,或者您处于不需要断开电路的情况。故障保险强制执行的行为很有可能是正确的方法。
如果您真的要这样做,请将重试逻辑放在发送给断路器的函数中,而不要使用故障安全中的RetryPolicy。或在重试策略中使用指数退避功能。