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

升级至Spring Boot 3.0.0(Apache HttpClient 5)遇DeadlineTimeoutException

问题

项目迁移至Java 17/Spring Boot 3.0.0后,部分集成测试失败。示例测试代码如下:

@Test
void getMessageInfos_Success_WithNonDefaultPeriodSent() throws Exception {
    var token = createToken();
    var ciUrlMessages = format("/%s/%s/messages;directions=%s;period=%s;maxCount=2000\?fetchText=false", CONTEXT, MAC, Direction.IN, 10);
    var ciUrlRecipients = format("/%s/%s/possible-recipients", CONTEXT, MAC);

    stub(GET, ciUrlMessages, okJson(loadJsonFromFile("/__files/inbox/inbox_standard_incomming_messages_without_text.json")));
    stub(GET, ciUrlRecipients, okJson(loadJsonFromFile("/__files/inbox/possible_recipients_only_agency.json")));

    mvc.perform(post(INBOX_MESSAGES_INFO_URL, CONTEXT, MAC)
                    .with(x509(CLIENT_CERT))
                    .header(AUTHORIZATION, BEARER + token)
                    .content(createMessageInfoRequestJsonForPeriodTests(true, 10))
                    .contentType(APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.[0].messageId", is("2943405")))
            .andExpect(jsonPath("$.[1].messageId", is("2899350")))
            .andExpect(jsonPath("$.[2].messageId", is("2896472")))
            .andExpect(jsonPath("$.[3].messageId", is("2855248")));

    verify(getRequestedFor(urlEqualTo(format("/%s/%s/messages;directions=%s;period=%s;maxCount=2000?fetchText=false", CONTEXT, MAC, Direction.IN, 10))));
    verify(getRequestedFor(urlEqualTo(ciUrlRecipients)));
}

调试时出现的异常栈:

java.util.concurrent.ExecutionException: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://localhost:56789/VjI7MTQ4NzU4NDE1NjAxNTs2MjE7QU9TOzI1MTE5ODA7MTI1NzMwODk5Mzs9O0F-OzI1MTE5ODI7RX47MjUxMTk4MQ/kzitRN6RuUabptLwyOx2y5-dE0A/messages;directions=IN;period=10;maxCount=2000": Request execution failed
    at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:396)
    at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2096)

根源异常:

Caused by: org.apache.hc.core5.util.DeadlineTimeoutException: Deadline: 292278994-08-17T09:12:55.807+0200, 9223370335509990168 MILLISECONDS overdue
    at org.apache.hc.core5.util.DeadlineTimeoutException.from(DeadlineTimeoutException.java:49)
    at org.apache.hc.core5.pool.StrictConnPool.lease(StrictConnPool.java:217)
    at org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager.lease(PoolingHttpClientConnectionManager.java:298)
    at org.apache.hc.client5.http.impl.classic.InternalExecRuntime.acquireEndpoint(InternalExecRuntime.java:103)
    ... 46 common frames omitted

此前使用Spring Boot 2.7.x(对应HttpClient 4)时,将connectionRequestTimeout、connectTimeout、SocketTimeout设为-1实现无超时。迁移到Apache HttpClient 5后,按文档将这些值设为0,但调试发现StrictConnPool.lease方法中执行acquiredLock = this.lock.tryLock(requestTimeout.getDuration(), requestTimeout.getTimeUnit());时,因requestTimeout.getDuration()为0,导致无法获取锁,抛出超时异常。

询问:若要实现无超时限制,requestTimeout应设置为何值?是否应在HttpConfiguration中将connectionRequestTimeout、connectTimeout、SocketTimeout设为Timeout.DISABLED?

解决方案

  • 核心结论:要实现无超时限制,必须使用Timeout.DISABLED而非数值0。
  • 原因分析:在Apache HttpClient 5中,数值0并非代表无超时,而是会被解析为立即超时(对应tryLock(0, timeUnit)会直接尝试获取锁,失败则立即抛出超时异常),这就是触发DeadlineTimeoutException的原因。
  • 具体配置方式:
    在配置HttpClient时,将connectionRequestTimeout、connectTimeout、socketTimeout都设置为Timeout.DISABLED,示例代码如下:
    HttpClient httpClient = HttpClientBuilder.create()
        .setConnectionTimeToLive(Timeout.DISABLED)
        .setDefaultRequestConfig(RequestConfig.custom()
            .setConnectTimeout(Timeout.DISABLED)
            .setConnectionRequestTimeout(Timeout.DISABLED)
            .setSocketTimeout(Timeout.DISABLED)
            .build())
        .build();
    
    若使用Spring Boot自动配置,可通过配置文件或自定义RestTemplate/HttpClient Bean来设置这些参数,确保所有超时参数都使用Timeout.DISABLED而非数值0或-1。
  • 验证逻辑:当使用Timeout.DISABLED时,requestTimeout.getDuration()会返回代表无限制的特殊值,此时tryLock方法会转为阻塞式获取锁(即调用lock()而非带超时的tryLock(...)),不会因超时导致锁获取失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 06:44:55