我们经常使用 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()));
...
此时我们读取输入流,直到 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() 不会完全关闭连接并将其从池中删除吗?