【问题标题】:Spring-Retry with Circuit breaker带断路器的弹簧重试
【发布时间】:2019-02-11 01:51:57
【问题描述】:

我正在尝试利用 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。在这种情况下,重试机制不起作用。请在下面找到代码 sn-p。

PS:exec 方法(Circuit Breaker 方法)是从控制器调用的。

@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。

【问题讨论】:

  • 我猜这是因为CircuitBreaker 本身就是一个Retryable
  • 是的,但是有什么方法可以配置吗?比如设置Backoff
  • 第一个不起作用,因为正如@yegodm 所说,它本身就是@Retryable - 请参阅我的答案以了解如何做到这一点。

标签: spring spring-retry circuit-breaker


【解决方案1】:

如果你想在断路器内重试,它们必须在不同的 bean 中。如果您在同一个 bean 中直接从另一个调用 @Retryable,您将绕过拦截器。

这对我来说很好......

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

    }

}

【讨论】:

  • 感谢您的回答。我也试图配置断路器的maxAttempts。似乎断路器的 maxAttempts 是恒定的,我们无法从属性文件进行配置。有什么解决方法吗?
  • 否;它不是;不像@Retryable,它没有...Expression-flavored 属性。也许打开一个新的功能请求问题against the project。我想您可以将其双重包装为解决方法-可重试调用一个断路器(带=1),该断路器调用可重试。
  • 感谢您的快速回复。但这并没有给我 opentimeout 和 resetTimeout 配置a
  • 对;他们需要在框架中更改代码才能进行配置。
  • 已经有一个open issue here。我去看看。
猜你喜欢
  • 2020-10-28
  • 1970-01-01
  • 2019-10-23
  • 2021-03-16
  • 2018-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-17
相关资源
最近更新 更多