Spring WebClient:使用WebFlux.fn + react-addons重试 [英] Spring WebClient: Retry with WebFlux.fn + reactor-addons

查看:262
本文介绍了Spring WebClient:使用WebFlux.fn + react-addons重试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Kotlin协程+ WebFlux.fn +反应堆插件为WebClient添加条件重试:

I'm trying to add a conditional Retry for WebClient with Kotlin Coroutines + WebFlux.fn + reactor-addons:

suspend fun ClientResponse.asResponse(): ServerResponse =
    status(statusCode())
        .headers { headerConsumer -> headerConsumer.addAll(headers().asHttpHeaders()) }
        .body(bodyToMono(DataBuffer::class.java), DataBuffer::class.java)
        .retryWhen { 
            Retry.onlyIf { ctx: RetryContext<Throwable> -> (ctx.exception() as? WebClientResponseException)?.statusCode in retryableErrorCodes }
                .exponentialBackoff(ofSeconds(1), ofSeconds(5))
                .retryMax(3)
                .doOnRetry { log.error("Retry for {}", it.exception()) }
        )
        .awaitSingle()

还在重试之前添加条件

if (statusCode().isError) {
        body(
            BodyInserters.fromPublisher(
                Mono.error(StatusCodeError(status = statusCode())),
                StatusCodeException::class.java
            )
        )
    } else {
        body(bodyToMono(DataBuffer::class.java), DataBuffer::class.java)
    }

通话如下:

suspend fun request(): ServerResponse =
           webClient/*...*/
                    .awaitExchange()
                    .asResponse()

推荐答案

This spring webclient: retry with backoff on specific error gave me the hint to answer the question:

.awaitExchange()返回ClientResponse而不是Mono<ClientReponse> 这意味着我的重试是针对bodyToMono而不是exchange()的操作.

.awaitExchange() returns the ClientResponse and not Mono<ClientReponse> This means my retry was acting on bodyToMono instead of the operation of exchange().

解决方案现在看起来像

suspend fun Mono<ClientResponse>.asResponse(): ServerResponse =
    flatMap {
        if (it.statusCode().isError) {
            Mono.error(StatusCodeException(status = it.statusCode()))
        } else {
            it.asResponse()
        }
    }.retryWhen(
        Retry.onlyIf { ctx: RetryContext<Throwable> ->
            (ctx.exception() as? StatusCodeException)?.shouldRetry() ?: false
        }
            .exponentialBackoff(ofSeconds(1), ofSeconds(5))
            .retryMax(3)
            .doOnRetry { log.error { it.exception() } }
    ).awaitSingle()

private fun ClientResponse.asResponse(): Mono<ServerResponse> =
    status(statusCode())
        .headers { headerConsumer -> headerConsumer.addAll(headers().asHttpHeaders()) }
        .body(bodyToMono(DataBuffer::class.java), DataBuffer::class.java)

这篇关于Spring WebClient:使用WebFlux.fn + react-addons重试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆