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

Spring Boot WebClient复用连接10分钟后ReadTimeoutException问题排查

问题

为何WebClient在首次请求10分钟后发起第二次请求时会抛出ReadTimeoutException?

环境:Spring Boot 3.3.5,原WebClient配置如下:

@Bean
public WebClient jsonApiWebClient() throws IOException {
    final ObjectMapper mapper = new ObjectMapper().findAndRegisterModules()
        .enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
    final ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
        .codecs(configurer -> configurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(mapper)))
        .build();
    SslContext sslContext = SslContextBuilder.forClient().protocols("TLSv1.2").build();
    //@formatter:off

    HttpClient httpClient = HttpClient
        .create()
        .secure(ssl -> ssl.sslContext(sslContext))
        .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 20 * 1000)
        .doOnConnected(
            conn ->
                conn.addHandlerLast(new ReadTimeoutHandler(35))
                    .addHandlerLast(new WriteTimeoutHandler(35))
        );
    //@formatter:on
    return WebClient.builder().defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
        .clientConnector(new ReactorClientHttpConnector(httpClient)).exchangeStrategies(exchangeStrategies).build();
}

将项目打包为War部署到Tomcat后,使用WebClient调用第三方API时,首次请求正常;10分钟后再次发起相同请求,会触发io.netty.handler.timeout.ReadTimeoutException。查看调试日志发现,首次请求完成后连接变为闲置状态,10分钟后再次请求复用了该闲置连接。

通过构建ConnectionProvider并设置pendingAcquireTimeout为5秒、maxIdleTime为30秒,修改为HttpClient.create(provider)后问题解决,疑问:是否因10分钟后会创建新的池化连接?

分析与解答

问题根源

Reactor Netty默认连接池的连接最大闲置时间(maxIdleTime)是无限期,闲置连接会一直留在池中。但第三方服务器或中间代理一般会设置连接闲置超时(比如10分钟),超时后服务器会主动断开连接,可客户端并不知情,依然会复用这个已经失效的连接。

当10分钟后复用该闲置连接发请求时,客户端向已被断开的连接发送数据,服务器不会响应,最终触发你配置的35秒读超时,抛出ReadTimeoutException。

修改后的解决原理

你配置的ConnectionProvider把maxIdleTime设为30秒,意味着池中闲置超过30秒的连接会被自动销毁。这样10分钟后的请求就不会复用那些被服务器断开的旧连接,只能创建新的有效连接,自然就避免了超时问题。

另外,pendingAcquireTimeout设为5秒是为了防止请求在连接池无可用连接时长时间等待,但这不是解决本次问题的核心,核心是maxIdleTime让过期闲置连接被及时清理。

所以你的疑问答案是:不是10分钟后才创建新连接,而是闲置超过30秒的连接已经被提前销毁,10分钟后的请求只能创建新的有效连接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 10:23:22