如果所有重试都用尽,Spring Webclient 重试并执行代码
Posted
技术标签:
【中文标题】如果所有重试都用尽,Spring Webclient 重试并执行代码【英文标题】:Spring Webclient retry and execute a code if all retries are exhausted 【发布时间】:2020-07-17 17:20:13 【问题描述】:我有一个将事件发送到不同来源 (URL) 的 webhook 服务。按照设计,请求超时为 10s,如果失败,则重试发送 3 次。如果所有重试均失败,则必须执行代码以禁用 DB 中的该 URL。
到目前为止,我设法重试并延迟了 5 秒。但是,我不确定如何在失败后执行代码。
try
String body = objectMapper.writeValueAsString(webhookDTO);
webClient.post()
.uri(webhook.getUrl())
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(body)
.exchange()
.timeout(Duration.ofSeconds(5))
.retryWhen(Retry.backoff(3, Duration.ofSeconds(5))
.jitter(0d)
.doAfterRetry(retrySignal ->
logger.info("Retried " + retrySignal.totalRetries());
)
.onRetryExhaustedThrow((retryBackoffSpec, retrySignal)
-> new WebhookTimeoutException()))
.doOnSuccess(clientResponse ->
logger.info("Event is received by " + client);
)
.subscribe();
catch (Exception e)
logger.error("Error on webhook dispatcher: ", e);
谁能举例说明如何做到这一点?
【问题讨论】:
在使用 Reactor 时请尽量避免使用 try-catch。 @PrashantPandey 感谢您的建议。你为什么这么认为? 【参考方案1】:你快到了!只需使用doOnError
,如下所示。这里的想法是,一旦所有尝试都失败了,你就抛出WebhookTimeoutException
。仅当抛出错误并更新数据库时才调用 doOnError。异常类是可选的。你可以忽略它。
webClient.post()
.uri(webhook.getUrl())
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(body)
.exchange()
.timeout(Duration.ofSeconds(5))
.retryWhen(Retry.backoff(3, Duration.ofSeconds(5))
.jitter(0d)
.doAfterRetry(retrySignal ->
logger.info("Retried " + retrySignal.totalRetries());
)
.onRetryExhaustedThrow((retryBackoffSpec, retrySignal)
-> new WebhookTimeoutException()))
.doOnSuccess(clientResponse ->
logger.info("Event is received by " + client);
)
.doOnError(WebhookTimeoutException.class, (msg) ->
System.out.println("Message :: " + msg);
// here update the DB
dbRepository.save(...);
)
.subscribe();
【讨论】:
哇。有效。干杯。我试过doOnError
,但在retryWhen()
之前。我不知道有什么区别:)
注意这里使用了RetrySpec
,在 reactor-core 3.3.4.RELEASE 中新引入(它允许使用特定的异常类来重试耗尽的情况,甚至可能是自定义的)以上是关于如果所有重试都用尽,Spring Webclient 重试并执行代码的主要内容,如果未能解决你的问题,请参考以下文章