使用Spring WebFlux中的webclient在Mono上有条件地重复或重试 [英] Conditional repeat or retry on Mono with webclient from Spring WebFlux
问题描述
我想做的是在带有webclient的Webflux中的Mono上有条件重复.情况如下:
What i want to do is a conditional repeat on a Mono in Webflux with webclient.The Situation is the following:
我们有一些商务休息服务服务,可返回生成的文档.该文档的生成是由在此服务之前被调用的另一服务触发的.但是,回到正题:文档生成服务需要10到30秒.我们要做的是:10秒钟后检查是否生成了文档(单声道).如果是这样,一切都很好.如果不是,请在5秒钟后重复(或重试)并检查是否生成了文档.依此类推,直到(最坏的情况)是30秒后超时.这可能吗?一些(伪)代码:
We have some business rest service service that returns a generated document. the generation of this document is triggered from another service that gets called before this one. But, back to business: the document generation service needs from 10-30 seconds. What we want to do is: check after 10 seconds if document (Mono) is generated. If so, all is fine. If not, repeat (or retry) after another 5 seconds and check if document is generated. And so on until (worst case) a timeout after 30 seconds. Is this possible? Some (pseudo) code:
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
has two concepts for re-subscribing (and thus, re-triggering the request)
- retry =重新订阅上游是否已完成
- 重复 =重新订阅上游是否成功完成
- retry = re-subscribe if the upstream completed with an exception
- repeat = re-subscribe if the upstream completed successfully
对于不同的用例,每个概念在Mono
上都有多个重载方法.查找retry*
和repeat*
方法.
例如,要无延迟地重试最大次数,请使用retry(int numRetries)
.
Each concept has multiple overloaded methods on Mono
for different use cases. Look for the retry*
and repeat*
methods.
For example, to retry a maximum number of times with no delay, use retry(int numRetries)
.
通过retryWhen
和repeatWhen
方法支持更复杂的用例,如以下示例所示.
More complex use cases are supported via the retryWhen
and repeatWhen
methods, as shown in the following examples.
要重试单声道是否异常完成最多5次,每次尝试之间间隔5秒:
To retry if the mono completed with an exception a maximum of 5 times with 5 seconds between each attempt:
// 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))
重试构建器支持其他退避策略(例如指数)和其他选项,以完全自定义重试.
The retry builder supports other backoff strategies (e.g. exponential) and other options to fully customize retries.
请注意,上面使用的retryWhen(Retry)
方法已添加到反应堆核心v3.3.4.RELEASE中,并且已弃用retryWhen(Function)
方法.
在反应堆核心v3.3.4.RELEASE之前,您可以使用
Note the retryWhen(Retry)
method used above was added in reactor-core v3.3.4.RELEASE, and the retryWhen(Function)
method was deprecated.
Prior to reactor-core v3.3.4.RELEASE, you could use the retry function builder from reactor-extras project to create a Function
to pass to retryWhen(Function)
.
如果需要成功重复一次,请使用.repeatWhen
或.repeatWhenEmpty
代替上面的.retryWhen
.
If you need to repeat on success, then use .repeatWhen
or .repeatWhenEmpty
instead of .retryWhen
above.
使用 reactor-extras reactor-extras 项目,以创建重复Function
,如下所示:
Use the repeat function builder from reactor-extras project to create the repeat Function
as follows:
// 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*
链接.
You can also chain a .retry*
with a .repeat*
if you want to re-subscribe on both success or failure.
这篇关于使用Spring WebFlux中的webclient在Mono上有条件地重复或重试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!