spring reactor retry.retrywhen()不起作用

0md85ypi  于 2021-07-24  发布在  Java
关注(0)|答案(1)|浏览(432)

如何使用重试?我想在出错时重试调用方法,直到成功为止。我的测试代码

@Test
    public void fun1() throws InterruptedException {
        this.generate()
                .retryWhen(Retry.fixedDelay(5, Duration.ofMillis(1))
                        .filter(e -> e instanceof Exception)
                        .doBeforeRetry(res -> System.out.println("retry begin"))
                        .doAfterRetry(res -> System.out.println("try finished")))
                .onErrorContinue((throwable, o) -> System.out.println(throwable))
                .subscribe(System.out::println);
    }

    private Mono<String> generate() throws InterruptedException {
        if (retryTime.get() == 3) {
            return Mono.just("Hello");
        }
        System.out.println("i am called" + retryTime.getAndAdd(1));
        return Mono.error(new IllegalArgumentException("exception test"));
    }

但是得到这个结果

i am called1
10:02:12.104 [main] DEBUG reactor.util.Loggers - Using Slf4j logging framework
retry begin
try finished
retry begin
try finished
retry begin
try finished
retry begin
try finished
retry begin
try finished
reactor.core.Exceptions$RetryExhaustedException: Retries exhausted: 5/5

Process finished with exit code 0

为什么不再试三次直到成功???

niwlg2el

niwlg2el1#

retry通过重新订阅上游方法的结果来工作。它不会重新调用上游方法。
特别是在您的情况下 .retryWhen 正在订阅 Mono.error 从对的单个调用返回 generate() . 因此,每个订阅都会看到相同的异常结果。
要解决这个问题,您需要推迟 generate() 方法在订阅时而不是在程序集时发生。
例如,使用 Mono.fromCallable ,如下所示:

private Mono<String> generate() {
        return Mono.fromCallable(() -> {
            if (retryTime.get() == 3) {
                return "Hello";
            }
            System.out.println("i am called" + retryTime.getAndAdd(1));
            throw new new IllegalArgumentException("exception test");
        });
    }

将为每个订户调用callable。具体来说,每次 retryWhen 操作员重新订阅。

相关问题