重试 Spring @HttpExchange

mun*_*nky 1 java spring webclient spring-boot

我使用Spring-boot-3 @GetExchangea WebClient,有时会遇到以下错误:

java.lang.IllegalStateException: Timeout on blocking read for 5000000000 NANOSECONDS
Run Code Online (Sandbox Code Playgroud)

如果使用来@GetExchange指示WebClient重试,最佳实践是什么?这个新注释没有足够的文档。

Cen*_*nni 5

您需要使用ExchangeFilterFunctions来帮助您定义重试逻辑。

    @Bean
    FooClient fooClient() {
        WebClient webClient =WebClient.builder()
            .baseUrl("your_base_url")
            .filter(withRetryableRequests())
            .build();
        HttpServiceProxyFactory factory=HttpServiceProxyFactory
            .builder(WebClientAdapter.forClient(webClient))
            .blockTimeout(Duration.of(HTTP_CLIENT_READ_TIMEOUT, ChronoUnit.SECONDS)) // Configure how long to wait for a response for an HTTP service method with a synchronous (blocking) method signature.By default this is 5 seconds.
            .build();
        return factory.createClient(FooClient.class);
    }

  
    private ExchangeFilterFunction withRetryableRequests() {
        return (request, next) -> next.exchange(request)
                .flatMap(clientResponse -> Mono.just(clientResponse)
                        .filter(response ->  clientResponse.statusCode().isError())
                        .flatMap(response -> clientResponse.createException())
                        .flatMap(Mono::error)
                        .thenReturn(clientResponse))
                .retryWhen(this.retryBackoffSpec());
    }
    
    private RetryBackoffSpec retryBackoffSpec() {
        return Retry.backoff(3, Duration.ofSeconds(2))
                .filter(throwable->throwable instanceof  WebClientResponseException) // here filter on the errors for which you want a retry
                .doBeforeRetry(retrySignal -> log.warn("Retrying request after following exception : {}",  retrySignal.failure().getLocalizedMessage()))
                .onRetryExhaustedThrow((retryBackoffSpec, retrySignal)  -> retrySignal.failure());
    }
Run Code Online (Sandbox Code Playgroud)

[编辑]对于您遇到的特殊情况,即异常

java.lang.IllegalStateException: Timeout on blocking read for 5000000000 NANOSECONDS
Run Code Online (Sandbox Code Playgroud)

可能的原因是您的服务正在等待请求的答复,5 秒后(默认情况下),服务挂起。

有必要增加所使用的 http 客户端的读取超时。我已相应地编辑了代码,并在相关行上添加了注释。