You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Apache HttpClient 5.4.1版本超时配置不生效问题求助:如何用非废弃类实现3秒超时

Apache HttpClient 5.4.1版本超时配置不生效问题求助:如何用非废弃类实现3秒超时

嗨,我来帮你解决这个头疼的问题!你遇到的超时不生效,核心原因是手动创建的DefaultClientTlsStrategy没有继承全局配置的Socket超时参数,导致HTTPS连接的SO_TIMEOUT没有被正确设置为3秒,才会等接口的5秒响应结束后才触发超时。

修正后的非废弃类配置代码

基于你原来的代码修改,完全使用非废弃类就能实现3秒超时:

public class HttpClientTimeoutExamplePoolingHttpClientConnectionManagerBuilder {
    public static void main(String[] args) {
        try {
            // 用DefaultClientTlsStrategyBuilder构建TLS策略,同时绑定Socket超时配置
            DefaultClientTlsStrategy tlsStrategy = DefaultClientTlsStrategyBuilder.create()
                    .setSslContext(SSLContext.getDefault())
                    .setSocketConfig(SocketConfig.custom()
                            .setSoTimeout(Timeout.of(3, TimeUnit.SECONDS))
                            .build())
                    .build();

            final PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
                    .setTlsSocketStrategy(tlsStrategy)
                    // 全局默认Socket配置,覆盖非HTTPS连接的超时
                    .setDefaultSocketConfig(SocketConfig.custom()
                            .setSoTimeout(Timeout.of(3, TimeUnit.SECONDS))
                            .build())
                    .setMaxConnPerRoute(20)
                    .setMaxConnTotal(200)
                    .build();

            final RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectionRequestTimeout(Timeout.of(1, TimeUnit.SECONDS))
                    .setConnectTimeout(Timeout.of(3, TimeUnit.SECONDS))
                    .setResponseTimeout(Timeout.of(3, TimeUnit.SECONDS))
                    .build();

            CloseableHttpClient httpClient = HttpClients.custom()
                    .setConnectionManager(connectionManager)
                    .setDefaultRequestConfig(requestConfig)
                    .evictExpiredConnections()
                    .build();

            // Create GET request
            final HttpGet httpGet = new HttpGet("https://httpbin.org/delay/5");
            httpGet.setConfig(requestConfig);

            // Log start time
            long startTime = System.currentTimeMillis();
            System.out.println("Executing GET request at: " + startTime);

            try {
                CloseableHttpResponse response = httpClient.execute(httpGet);
                try {
                    long endTime = System.currentTimeMillis();
                    System.out.println("Response received after: " + (endTime - startTime) + "ms");
                    System.out.println("Response status: " + response.getCode());
                    System.out.println("Response body: " + EntityUtils.toString(response.getEntity()));
                } finally {
                    response.close();
                }
            } catch (Exception e) {
                long endTime = System.currentTimeMillis();
                System.out.println("Exception after: " + (endTime - startTime) + "ms");
                System.out.println("Exception type: " + e.getClass().getName());
                System.out.println("Exception message: " + e.getMessage());
                e.printStackTrace();
            } finally {
                httpClient.close();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

为什么这样修改能生效?

  • 你之前直接创建DefaultClientTlsStrategy时,没有传入自定义的SocketConfig,导致HTTPS连接使用了默认的SO_TIMEOUT(通常为0,即永不超时),所以会等接口的5秒响应结束。
  • 现在用DefaultClientTlsStrategyBuilder构建TLS策略,明确绑定了3秒的SO_TIMEOUT,让HTTPS连接遵守超时规则。
  • 保留全局setDefaultSocketConfig是为了确保非HTTPS的HTTP连接也能应用相同的超时配置。

更简洁的替代方案(无需手动处理TLS策略)

如果不需要自定义SSLContext,可以让连接管理器自动创建默认TLS策略,全局SocketConfig会自动应用到所有连接,代码更清爽:

final PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
        .setDefaultSocketConfig(SocketConfig.custom()
                .setSoTimeout(Timeout.of(3, TimeUnit.SECONDS))
                .build())
        .setMaxConnPerRoute(20)
        .setMaxConnTotal(200)
        .build();

这样就不用手动创建DefaultClientTlsStrategy,Builder会自动处理所有类型连接的配置,超时规则也能正常生效。

补充说明

  • ResponseTimeout是HttpClient层面的超时逻辑,它依赖于底层Socket的SO_TIMEOUT实现,所以确保SO_TIMEOUT正确设置是核心。
  • 你之前用废弃Registry方式生效,是因为旧的SocketFactory会直接读取连接管理器的DefaultSocketConfig,而手动创建的TLS策略没有继承这个配置,才导致了差异。

修改后,你的请求应该会在3秒左右触发超时,和用废弃类的效果完全一致,同时所有使用的类都是非废弃的。

备注:内容来源于stack exchange,提问作者newLearner

火山引擎 最新活动