Spring-使用断路器重试
Spring-Retry with Circuit breaker
我正在尝试利用 spring-retry 的重试和断路器机制。
我尝试在特定功能(如下所示)中同时使用注释(@Retryable 和 @CircuitBreaker),但断路器无法正常工作。
@Service
public class CommandAndRetry {
private static final Logger LOGGER = LoggerFactory.getLogger(SampleRetryService.class);
@CircuitBreaker(maxAttempts = 1, openTimeout = 10000)
@Retryable(
value = {TypeOneException.class},
maxAttempts = 3, backoff = @Backoff(2000))
public void retryWhenException() throws TypeOneException {
LOGGER.info("Retrying");
throw new TypeOneException();
}
@Recover
public void recover(Throwable t) throws Throwable {
LOGGER.info("SampleRetryService.recover");
throw t;
}
}
然后我尝试将功能分为两个不同的功能,分别具有@Retryable 和@CircuitBreaker。在这种情况下,重试机制不起作用。请在下面找到代码片段。
PS: 从控制器调用 exec 方法(断路器方法)。
@Service
public class CommandAndRetry {
private static final Logger LOGGER = LoggerFactory.getLogger(SampleRetryService.class);
@CircuitBreaker(maxAttempts = 1, openTimeout = 10000)
public void exec() throws TypeOneException {
retryWhenException();
}
@Retryable(
value = {TypeOneException.class},
maxAttempts = 3, backoff = @Backoff(2000))
public void retryWhenException() throws TypeOneException {
LOGGER.info("Retrying");
throw new TypeOneException();
}
@Recover
public void recover(Throwable t) throws Throwable {
LOGGER.info("SampleRetryService.recover");
throw t;
}
}
谁能告诉我为什么会这样。
另请告知是否有更好的方法来实现重试和断路器。
PS:我既不想使用 resilience4j,也不想使用 retryTemplate。
如果你想在断路器中重试,它们必须在不同的 bean 中。如果您直接从另一个调用一个 @Retryable
,在同一个 bean 中,您将绕过拦截器。
这对我来说很好...
@SpringBootApplication
@EnableRetry
public class So52193237Application {
public static void main(String[] args) {
SpringApplication.run(So52193237Application.class, args);
}
@Bean
public ApplicationRunner runner(Foo foo) {
return args -> {
try {
foo.exec();
}
catch (Exception e) {
try {
foo.exec();
}
catch (Exception ee) {
Thread.sleep(11000);
try {
foo.exec();
}
catch (Exception eee) {
}
}
}
};
}
@Component
public static class Foo {
private static final Logger LOGGER = LoggerFactory.getLogger(Foo.class);
private final Bar bar;
public Foo(Bar bar) {
this.bar = bar;
}
@CircuitBreaker(maxAttempts = 1, openTimeout = 10000, resetTimeout=10000)
public void exec() throws TypeOneException {
LOGGER.info("Foo.circuit");
this.bar.retryWhenException();
}
@Recover
public void recover(Throwable t) throws Throwable {
LOGGER.info("Foo.recover");
throw t;
}
}
@Component
public static class Bar {
private static final Logger LOGGER = LoggerFactory.getLogger(Bar.class);
@Retryable(value = { TypeOneException.class }, maxAttempts = 3, backoff = @Backoff(2000))
public void retryWhenException() throws TypeOneException {
LOGGER.info("Retrying");
throw new TypeOneException();
}
@Recover
public void recover(Throwable t) throws Throwable {
LOGGER.info("Bar.recover");
throw t;
}
}
}
我正在尝试利用 spring-retry 的重试和断路器机制。 我尝试在特定功能(如下所示)中同时使用注释(@Retryable 和 @CircuitBreaker),但断路器无法正常工作。
@Service
public class CommandAndRetry {
private static final Logger LOGGER = LoggerFactory.getLogger(SampleRetryService.class);
@CircuitBreaker(maxAttempts = 1, openTimeout = 10000)
@Retryable(
value = {TypeOneException.class},
maxAttempts = 3, backoff = @Backoff(2000))
public void retryWhenException() throws TypeOneException {
LOGGER.info("Retrying");
throw new TypeOneException();
}
@Recover
public void recover(Throwable t) throws Throwable {
LOGGER.info("SampleRetryService.recover");
throw t;
}
}
然后我尝试将功能分为两个不同的功能,分别具有@Retryable 和@CircuitBreaker。在这种情况下,重试机制不起作用。请在下面找到代码片段。
PS: 从控制器调用 exec 方法(断路器方法)。
@Service
public class CommandAndRetry {
private static final Logger LOGGER = LoggerFactory.getLogger(SampleRetryService.class);
@CircuitBreaker(maxAttempts = 1, openTimeout = 10000)
public void exec() throws TypeOneException {
retryWhenException();
}
@Retryable(
value = {TypeOneException.class},
maxAttempts = 3, backoff = @Backoff(2000))
public void retryWhenException() throws TypeOneException {
LOGGER.info("Retrying");
throw new TypeOneException();
}
@Recover
public void recover(Throwable t) throws Throwable {
LOGGER.info("SampleRetryService.recover");
throw t;
}
}
谁能告诉我为什么会这样。
另请告知是否有更好的方法来实现重试和断路器。 PS:我既不想使用 resilience4j,也不想使用 retryTemplate。
如果你想在断路器中重试,它们必须在不同的 bean 中。如果您直接从另一个调用一个 @Retryable
,在同一个 bean 中,您将绕过拦截器。
这对我来说很好...
@SpringBootApplication
@EnableRetry
public class So52193237Application {
public static void main(String[] args) {
SpringApplication.run(So52193237Application.class, args);
}
@Bean
public ApplicationRunner runner(Foo foo) {
return args -> {
try {
foo.exec();
}
catch (Exception e) {
try {
foo.exec();
}
catch (Exception ee) {
Thread.sleep(11000);
try {
foo.exec();
}
catch (Exception eee) {
}
}
}
};
}
@Component
public static class Foo {
private static final Logger LOGGER = LoggerFactory.getLogger(Foo.class);
private final Bar bar;
public Foo(Bar bar) {
this.bar = bar;
}
@CircuitBreaker(maxAttempts = 1, openTimeout = 10000, resetTimeout=10000)
public void exec() throws TypeOneException {
LOGGER.info("Foo.circuit");
this.bar.retryWhenException();
}
@Recover
public void recover(Throwable t) throws Throwable {
LOGGER.info("Foo.recover");
throw t;
}
}
@Component
public static class Bar {
private static final Logger LOGGER = LoggerFactory.getLogger(Bar.class);
@Retryable(value = { TypeOneException.class }, maxAttempts = 3, backoff = @Backoff(2000))
public void retryWhenException() throws TypeOneException {
LOGGER.info("Retrying");
throw new TypeOneException();
}
@Recover
public void recover(Throwable t) throws Throwable {
LOGGER.info("Bar.recover");
throw t;
}
}
}