spring reactor retry.retrywhen()不起作用

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

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

  1. @Test
  2. public void fun1() throws InterruptedException {
  3. this.generate()
  4. .retryWhen(Retry.fixedDelay(5, Duration.ofMillis(1))
  5. .filter(e -> e instanceof Exception)
  6. .doBeforeRetry(res -> System.out.println("retry begin"))
  7. .doAfterRetry(res -> System.out.println("try finished")))
  8. .onErrorContinue((throwable, o) -> System.out.println(throwable))
  9. .subscribe(System.out::println);
  10. }
  11. private Mono<String> generate() throws InterruptedException {
  12. if (retryTime.get() == 3) {
  13. return Mono.just("Hello");
  14. }
  15. System.out.println("i am called" + retryTime.getAndAdd(1));
  16. return Mono.error(new IllegalArgumentException("exception test"));
  17. }

但是得到这个结果

  1. i am called1
  2. 10:02:12.104 [main] DEBUG reactor.util.Loggers - Using Slf4j logging framework
  3. retry begin
  4. try finished
  5. retry begin
  6. try finished
  7. retry begin
  8. try finished
  9. retry begin
  10. try finished
  11. retry begin
  12. try finished
  13. reactor.core.Exceptions$RetryExhaustedException: Retries exhausted: 5/5
  14. Process finished with exit code 0

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

niwlg2el

niwlg2el1#

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

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

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

相关问题