You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在集中配置处为Reactive WebClient添加统一重试策略

为WebClient添加统一重试策略的方案

针对你已有的WebClient配置,有两种集中式的统一重试实现方案,无需修改每个API调用的代码:

方案一:通过ExchangeFilterFunction在WebClient层面拦截重试

ExchangeFilterFunction是WebClient的请求拦截器,可统一处理所有请求的响应,在此处添加重试逻辑,适合针对HTTP响应状态码(如5xx)的重试场景。

修改后的WebClient构建代码:

ObjectMapper objectMapper = new ObjectMapper();
ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
        .codecs(configure ->
                configure
                        .defaultCodecs()
                        .jackson2JsonDecoder(
                                new Jackson2JsonDecoder(objectMapper)))
        .build();

HttpClient httpClient = HttpClient.create()
        .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 12000)
        .responseTimeout(Duration.ofMillis(60000));

// 定义统一重试拦截器
ExchangeFilterFunction retryFilter = ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
    // 针对5xx状态码触发重试(可根据需求扩展其他重试条件,如特定4xx)
    if (clientResponse.statusCode().is5xxServerError()) {
        return Mono.error(new RuntimeException("Server error, trigger retry"));
    }
    return Mono.just(clientResponse);
}).retryWhen(Retry.backoff(3, Duration.ofSeconds(1))  // 最多重试3次,每次间隔1秒指数退避
        .filter(throwable -> {
            // 仅对指定异常类型重试:包括自定义的响应错误异常、IO类异常
            return throwable instanceof RuntimeException || throwable instanceof IOException;
        })
        .onRetryExhaustedThrow((retryBackoffSpec, retrySignal) -> {
            // 重试耗尽后抛出指定异常
            return new IllegalStateException("Max retries reached");
        }));

return WebClient.builder()
        .exchangeStrategies(exchangeStrategies)
        .clientConnector(new ReactorClientHttpConnector(httpClient))
        .baseUrl(modelDeployConfig.getHost())
        .defaultHeaders(h -> {
            h.setContentType(MediaType.APPLICATION_JSON);
            h.setAccept(List.of(MediaType.APPLICATION_JSON));
        })
        .filter(retryFilter)  // 添加重试拦截器
        .build();

扩展说明:

  • 可通过clientResponse.statusCode()判断更多重试条件,比如429 Too Many Requests
  • 若需区分请求方法(仅幂等方法如GET、PUT重试),可在拦截器中添加请求方法判断逻辑:
    .ofRequestProcessor(request -> {
        if (HttpMethod.POST.equals(request.method())) {
            return Mono.just(request); // POST非幂等,跳过重试
        }
        return Mono.just(request);
    })
    

方案二:在HttpClient层面配置底层重试

适合处理底层IO异常(如连接超时、读取超时),直接在Reactor HttpClient中配置重试策略,所有通过该Client的请求都会自动重试。

修改后的HttpClient配置代码:

HttpClient httpClient = HttpClient.create()
        .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 12000)
        .responseTimeout(Duration.ofMillis(60000))
        .retry(Retry.backoff(3, Duration.ofSeconds(1))
                .filter(throwable -> {
                    // 针对连接超时、读取超时等IO异常重试
                    return throwable instanceof ConnectException || 
                           throwable instanceof ReadTimeoutException ||
                           throwable instanceof IOException;
                })
                .onRetryExhaustedThrow((spec, signal) -> new IllegalStateException("Max retries for IO errors reached")));

组合方案

实际场景中可同时使用两种方案:

  • HttpClient层面处理底层IO异常重试
  • ExchangeFilterFunction处理HTTP响应状态码的业务重试

这样能覆盖大部分需要重试的场景,且完全集中配置,无需修改现有API调用代码。

内容的提问来源于stack exchange,提问作者Onisha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 12:35:28