如何在集中配置处为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
相关产品推荐
相关产品推荐

