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

Spring Boot 3.2.2 RestClient首次调用API报I/O错误的解决及HTTP版本设置方法

问题解决方案

一、首次请求I/O错误的解决方案

该错误多因首次请求时TCP连接建立异常、第三方API服务冷启动,或RestClient默认连接配置不匹配导致,以下是可行解决办法:

  • 配置连接池与超时参数
    RestClient默认使用的SimpleClientHttpRequestFactory无连接池,首次请求需新建连接,易出现超时或连接异常。可切换至基于Apache HttpClient或OkHttp的连接池配置,同时设置合理超时时间:
    示例代码(Apache HttpClient):

    @Bean
    public RestClient restClient() {
        HttpClient httpClient = HttpClientBuilder.create()
                .setMaxConnTotal(100)
                .setMaxConnPerRoute(20)
                .setConnectionTimeOut(Timeout.ofSeconds(5))
                .setResponseTimeout(Timeout.ofSeconds(10))
                .build();
    
        ClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
    
        return RestClient.builder()
                .requestFactory(factory)
                .build();
    }
    

    配置后连接会被复用,避免首次请求的连接建立问题。

  • 添加重试机制
    针对首次请求偶发失败的情况,给RestClient添加重试逻辑,可使用Spring的RetryTemplate实现:

    @Bean
    public RetryTemplate retryTemplate() {
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
        retryPolicy.setMaxAttempts(2); // 重试1次,共发起2次请求
    
        FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
        backOffPolicy.setBackOffPeriod(1000); // 间隔1秒重试
    
        RetryTemplate retryTemplate = new RetryTemplate();
        retryTemplate.setRetryPolicy(retryPolicy);
        retryTemplate.setBackOffPolicy(backOffPolicy);
        return retryTemplate;
    }
    
    // 调用时包裹请求逻辑
    ResponseEntity<Response> responseEntity = retryTemplate.execute(context -> 
        restClient.post()
            .uri("%s/veriy".formatted(config.getUrl()))
            .header("x-api-key", config.getKey())
            .body(requestBody)
            .retrieve()
            .toEntity(Response.class)
    );
    
  • 检查第三方API连接要求
    确认第三方API是否强制要求特定HTTP版本、是否需要开启Keep-Alive,或是否有IP白名单/初始验证机制,这些都可能导致首次请求失败。

二、RestClient中配置HTTP版本的方法

Spring Boot 3.2.2中,RestClient需通过自定义ClientHttpRequestFactory指定HTTP版本,以下是两种常见实现方式:

方式1:基于Apache HttpClient配置

@Bean
public RestClient restClient() {
    HttpClient httpClient = HttpClientBuilder.create()
            .setVersion(HttpVersion.HTTP_1_1) // 可替换为HTTP_2
            .build();

    ClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);

    return RestClient.builder()
            .requestFactory(factory)
            .build();
}

需提前引入Apache HttpClient依赖:

<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
</dependency>

方式2:基于OkHttp配置

@Bean
public RestClient restClient() {
    OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .protocols(List.of(Protocol.HTTP_1_1)) // 指定HTTP版本
            .build();

    ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory(okHttpClient);

    return RestClient.builder()
            .requestFactory(factory)
            .build();
}

需提前引入OkHttp依赖:

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
</dependency>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 13:44:56