如何保持多个Java HttpConnections对同一目的地开放

Lig*_*ard 6 java servlets http tcpclient httpurlconnection

我们正在使用HttpURLConnection API来经常向同一个提供程序调用REST API(一种聚合用例).我们希望保持对提供者主机始终开放的5个连接池(始终是相同的IP).

什么是正确的解决方案?这是我们尝试的:


System.setProperty("http.maxConnections", 5);  // set globally only once
...
// everytime we need a connection, we use the following
HttpURLConnection conn = (HttpURLConnection) (new URL(url)).openConnection();
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.setDoOutput(false);
conn.setUseCaches(true);
...
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
...
Run Code Online (Sandbox Code Playgroud)

此时我们读取输入流,直到BufferedReader不再返回字节为止.如果我们想要重用与提供者的底层连接,那么在那之后我们该怎么做?我们的印象是,如果完全读取输入流,则将连接添加回池中.

它以这种方式工作了几个星期,但今天它停止工作产生这个异常: java.net.SocketException: Too many open files

我们在CLOSE_WAIT状态下发现了许多套接字(通过运行lsof): java 1814 root 97u IPv6 844702 TCP colinux:58517->123.123.254.205:www (CLOSE_WAIT)

conn.getInputStream().close()或conn.disconnect()是否会完全关闭连接并将其从池中删除?

ZZ *_*der 5

我们在 Java 5 上也遇到了这个问题,我们的解决方案是使用池化连接管理器切换到 Apache HttpClient。

Sun 的 HTTP 的 URL 处理程序的 keepalive 实现有很多问题。没有维护线程来关闭空闲连接。

keepalive 的另一个更大问题是您需要删除响应。否则,连接也将是孤立的。大多数人没有正确处理错误流。有关如何正确读取错误响应的示例,请参阅我对此问题的回答,

HttpURLConnection.getResponseCode() 在第二次调用时返回 -1


Ale*_*ing 4

这里

当前的实现不缓冲响应正文。这意味着应用程序必须完成读取响应正文或调用 close() 放弃响应正文的其余部分,以便重用该连接。此外,当前的实现在清理连接时不会尝试块读取,这意味着如果整个响应正文不可用,则将不会重用该连接。

我读到这篇文章就好像您的解决方案应该有效,但您也可以自由调用 close 并且连接仍将被重用。