使用来自 Spring WebFlux 的 webclient 在 Mono 上有条件地重复或重试
Conditional repeat or retry on Mono with webclient from Spring WebFlux
我想做的是在 Webflux 中的 Mono 上有条件地重复 webclient.The 情况如下:
我们有一些业务休息服务服务,returns 生成文档。此文档的生成是由在此之前调用的另一个服务触发的。但是,言归正传:文档生成服务需要 10-30 秒。我们要做的是:10 秒后检查是否生成了文档 (Mono)。如果是这样,一切都很好。如果没有,再过 5 秒后重复(或重试)并检查是否生成了文档。依此类推,直到(最坏的情况)30 秒后超时。这可能吗?一些(伪)代码:
return this.webClient.post().uri(SERVICE_URL)).
body(BodyInserters.fromObject(docRequest)).retrieve().
bodyToMono(Document.class).
delaySubscription(Duration.ofSeconds(10)).
repeat5TimesWithDynamicTimeDelayUntil(!document.isEmpty()).
subscribe();
你好
贝尔纳多
是的,有可能。
Mono
有两个重新订阅的概念(因此,重新触发请求)
- 重试 = 如果上游完成异常则重新订阅
- 重复 = 如果上游成功完成则重新订阅
每个概念在 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*
链接起来。
我想做的是在 Webflux 中的 Mono 上有条件地重复 webclient.The 情况如下:
我们有一些业务休息服务服务,returns 生成文档。此文档的生成是由在此之前调用的另一个服务触发的。但是,言归正传:文档生成服务需要 10-30 秒。我们要做的是:10 秒后检查是否生成了文档 (Mono)。如果是这样,一切都很好。如果没有,再过 5 秒后重复(或重试)并检查是否生成了文档。依此类推,直到(最坏的情况)30 秒后超时。这可能吗?一些(伪)代码:
return this.webClient.post().uri(SERVICE_URL)).
body(BodyInserters.fromObject(docRequest)).retrieve().
bodyToMono(Document.class).
delaySubscription(Duration.ofSeconds(10)).
repeat5TimesWithDynamicTimeDelayUntil(!document.isEmpty()).
subscribe();
你好 贝尔纳多
是的,有可能。
Mono
有两个重新订阅的概念(因此,重新触发请求)
- 重试 = 如果上游完成异常则重新订阅
- 重复 = 如果上游成功完成则重新订阅
每个概念在 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*
链接起来。