Apache HttpClient 5 池无超时

问题描述 投票:0回答:1

我们正在从 Apache HttpClient 4.5 升级到 5.2,池超时的工作方式似乎发生了重大变化。我们希望配置池,使其具有固定数量的可用连接,但其他线程根本不等待。由于非正值被视为无限超时,因此我们将 ConnectionRequestTimeout 设置为 1 毫秒,以便它检查空闲连接,如果池耗尽,它几乎会立即失败。

在 4.5 中,这种方法工作得很好,但在 5.2 中,似乎过早地检查了超时,并且在应该仍然有可用连接时失败了。这是一个可以相当可靠地为我重现问题的测试:

class Test {

    static CloseableHttpClient client;

    public static void main(String[] args) {
        var requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(Timeout.ofMilliseconds(1))
                .build();

        var connManager = new PoolingHttpClientConnectionManager();
        connManager.setMaxTotal(50);
        connManager.setDefaultMaxPerRoute(50);

        client = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connManager)
                .build();

        for (int i = 0; i < 45; i++) {
            new Requester().start();
        }
    }

    static class Requester extends Thread {
        String result;

        @Override
        public void run() {
            try {
                result = client.execute(new HttpGet("https://www.example.com"), ClassicHttpResponse::toString);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

这会输出一系列堆栈跟踪,如下所示:

org.apache.hc.client5.http.impl.classic.RequestFailedException: Request execution failed
    at org.apache.hc.client5.http.impl.classic.InternalExecRuntime.acquireEndpoint(InternalExecRuntime.java:131)
    at org.apache.hc.client5.http.impl.classic.ConnectExec.execute(ConnectExec.java:125)
    at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
    at org.apache.hc.client5.http.impl.classic.ProtocolExec.execute(ProtocolExec.java:192)
    at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
    at org.apache.hc.client5.http.impl.classic.HttpRequestRetryExec.execute(HttpRequestRetryExec.java:113)
    at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
    at org.apache.hc.client5.http.impl.classic.ContentCompressionExec.execute(ContentCompressionExec.java:152)
    at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
    at org.apache.hc.client5.http.impl.classic.RedirectExec.execute(RedirectExec.java:116)
    at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
    at org.apache.hc.client5.http.impl.classic.InternalHttpClient.doExecute(InternalHttpClient.java:170)
    at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:245)
    at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:188)
    at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:162)
    at Test$Requester.run(Test.java:40)
Caused by: org.apache.hc.core5.util.DeadlineTimeoutException: Deadline: 2024-01-10T02:02:37.621+0000, -15 MILLISECONDS overdue
    at org.apache.hc.core5.util.DeadlineTimeoutException.from(DeadlineTimeoutException.java:49)
    at org.apache.hc.core5.pool.StrictConnPool.lease(StrictConnPool.java:222)
    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)
    ... 15 more

将超时增加到 25 毫秒可以减少超时的频率,但偶尔也会发生。这是一个错误吗?是否有另一种方法可以配置具有低(或无)超时的池?

java timeout apache-httpclient-4.x apache-httpclient-5.x connection-pool
1个回答
0
投票

为什么要使用连接超时来实现它? 在 HttpClient 上使用它 .evictIdleConnections(Timeout.ofMilliseconds(1))

© www.soinside.com 2019 - 2024. All rights reserved.