是的,有可能。
Mono 有两个概念用于重新订阅(从而重新触发请求)
-
重试 = 如果上游完成异常则重新订阅
-
repeat = 如果上游成功完成则重新订阅
每个概念在Mono 上都有多个针对不同用例的重载方法。寻找 retry* 和 repeat* 方法。
例如,要无延迟地重试最大次数,请使用retry(int numRetries)。
通过retryWhen 和repeatWhen 方法支持更复杂的用例,如以下示例所示。
重试时
如果单声道以异常完成最多 5 次,每次尝试之间间隔 5 秒,则重试:
// From reactor-core >= v3.3.4.RELEASE
import reactor.util.retry.Retry;
this.webClient
.post()
.uri(SERVICE_URL)
.body(BodyInserters.fromValue(docRequest))
.retrieve()
.bodyToMono(Document.class)
.retryWhen(Retry.fixedDelay(5, Duration.ofSeconds(5)))
.delaySubscription(Duration.ofSeconds(10))
重试构建器支持其他退避策略(例如指数)和其他选项以完全自定义重试。
请注意,上面使用的 retryWhen(Retry) 方法是在 reactor-core v3.3.4.RELEASE 中添加的,而 retryWhen(Function) 方法已被弃用。
在 reactor-core v3.3.4.RELEASE 之前,您可以使用来自 reactor-extras 项目的重试函数构建器来创建一个 Function 以传递给 retryWhen(Function)。
重复时
如果您需要在成功时重复,请使用.repeatWhen 或.repeatWhenEmpty 而不是上面的.retryWhen。
使用来自reactor-extras 项目的重复函数构建器来创建重复Function,如下所示:
// From reactor-extras
import reactor.retry.Repeat;
this.webClient
.post()
.uri(SERVICE_URL)
.body(BodyInserters.fromValue(docRequest))
.retrieve()
.bodyToMono(Document.class)
.filter(document -> !document.isEmpty())
.repeatWhenEmpty(Repeat.onlyIf(repeatContext -> true)
.exponentialBackoff(Duration.ofSeconds(5), Duration.ofSeconds(10))
.timeout(Duration.ofSeconds(30)))
.delaySubscription(Duration.ofSeconds(10))
如果您想在成功或失败时重新订阅,也可以将.retry* 与.repeat* 链接起来。