4

我有一个在亚马逊的 EC2 上运行的多线程 Java 程序。它使用 org.apache.http.impl.client.DefaultHttpClient 通过 HttpPost 和 HttpGet 从供应商处查询和获取数据项。同时,它使用 AWS 的 Java SDK 将检索到的数据项推送到 S3。

运行几天后,我得到了通常伴随 http 连接泄漏的症状:

org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection
at org.apache.http.impl.conn.tsccm.ConnPoolByRoute.getEntryBlocking(ConnPoolByRoute.java:417)
at org.apache.http.impl.conn.tsccm.ConnPoolByRoute$1.getPoolEntry(ConnPoolByRoute.java:300)
at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager$1.getConnection(ThreadSafeClientConnManager.java:224)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:391)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732)

由于 AWS 和我对数据供应商的请求都使用 Http 连接,所以我不太确定我到底忘记了哪里HttpEntity.consume(),或者S3ObjectInputStream.close()(除非它还有其他东西......)。

所以这是我的问题:有没有办法进行监控org.apache.http.impl.conn.tsccm.ConnPoolByRoute,以便至少我可以检测到我何时开始泄漏连接/实体未正确使用/http 流未关闭?(我感觉它只在某些条件下发生,例如当某些异常被抛出时,绕过我的代码中消耗 HttpEntities、关闭流等的逻辑。)关于如何诊断最终导致我所有 http 的任何想法因 ConnectionPoolTimeoutException 而失败的连接将是最受欢迎的。我不想在尝试解决问题的根本原因之间等待 4 天以上。

4

2 回答 2

5

如果您正在使用PoolingClientConnectionManager注释,则有一些方法getTotalStats()getStats(final HttpRoute route)它们将为您提供一个 PoolStats 对象,其中包含您要监视的数据。

只需从您的 httpclient 获取 ConnectionManager:

PoolingClientConnectionManager poolManager = (PoolingClientConnectionManager) httpClient.getConnectionManager();
于 2012-12-17T14:56:14.410 回答
1

如果您可以访问,org.apache.http.impl.conn.tsccm.ConnPoolByRoute则将其 connTTL 设置为足够低的值,以便WaitingThreadAborter最终终止连接。它会在那里显示一个很好的堆栈跟踪。另一种选择是使用 CGLIB 或其他一些字节码操作框架来创建代理类包装org.apache.http.impl.conn.tsccm.ConnPoolByRoute。根据您的环境,设置它可能并不那么容易,但它是一个非常有价值的工具来调试像您这样的问题。(是的,如果你碰巧使用 spring 或者只是简单的 Aspects,那么设置将会非常简单:))

于 2012-06-27T02:08:45.433 回答