Apache PoolingHttpClientConnectionManager抛出非法状态异常

29

这是我如何使用它 -

private static final PoolingHttpClientConnectionManager connPool;

static {

        connPool = new PoolingHttpClientConnectionManager();
        // Increase max total connection to 200
        connPool.setMaxTotal(200);//configurable through app.properties
        // Increase default max connection per route to 50
        connPool.setDefaultMaxPerRoute(20);//configurable through app.properties

}

CloseableHttpClient httpClient = HttpClients.custom()
                .setConnectionManager(connPool) .build();

我也在http GET周围加入了一个finally块-

finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                LOGGER.error(e.getMessage());   
            }
        }

这是我的堆栈跟踪 -

java.lang.IllegalStateException: Connection pool shut down
    at org.apache.http.util.Asserts.check(Asserts.java:34)
    at org.apache.http.pool.AbstractConnPool.lease(AbstractConnPool.java:169)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.requestConnection(PoolingHttpClientConnectionManager.java:217)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:157)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:194)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:85)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
    at com.A.B.C.CustomHttpClient.doGETAndValidate(CustomHttpClient.java:44)
    at com.A.B.C.SiteMonitorTask.monitorAndUpdateEndPoints(SiteMonitorTask.java:48)
    at com.A.B.C.SiteMonitorTask.run(SiteMonitorTask.java:37)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

我正在使用Quartz调度一个监控Http端点的作业。这是我的连接池配置

totalMaxHttpConn=200
maxHttpConnPerRoute=20

Maven 依赖,艺术品版本

httpclient 4.3.1
httpcore 4.3.1

编辑 - 问题解决了,原因是在finally块中没有关闭CloseableHttpClient。有人能告诉我为什么会这样吗?如果我关闭客户端,为什么连接池会关闭?

上面的closeablehttpclient是一个池子的句柄,而不是单个连接吗?


你的代码中访问池的部分在哪里?我猜在你访问它时,有人或某些东西关闭了这个池。 - Praba
以上的代码是否足够? - abipc
正在寻找一个合适的文档链接来解释这个问题。你应该释放连接而不是关闭它。你并没有真正关闭客户端。换句话说,客户端是你创建到 HTTP URL 的实际连接。 - Praba
没有像CloseableHttpClient的release connection这样的API。 - abipc
3
这个链接或许可以帮到你:http://www.baeldung.com/httpclient-connection-management - Praba
2个回答

58
在版本4.4中,HttpClientBuilder添加了setConnectionManagerShared(boolean)方法。
如果将其设置为true,则客户端不会关闭连接管理器。
HttpClients.custom()
            .setConnectionManager(Util.getConnectionManager()) // shared connection manager
            .setConnectionManagerShared(true)

11

这种行为是由HC 4.3中的一个错误导致的。已经在HC 4.4a1中修复。从4.4版本开始,CloseableHttpClient#close仅在连接池被客户端独占时自动关闭。


你知道这个 bug 的 ID 吗? - abipc
如果你愿意的话,我可以告诉你修订号码,但是对于这个缺陷没有提出任何故障工单。 - ok2c
目前已通过删除httpClient.close()解决了问题。没有测试oleg提供的版本号。 - abipc
2
我正在使用Jersey2.6,由PoolingHttpClientConnectionManager支持。它会有相同的问题吗? - macemers
这与我在4.5版本中观察到的不同。虽然注册了多个客户端,但连接管理器仍将关闭。setConnectionManagerShared()解决了这个问题。 - Telegrapher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接