how to keep multiple Java HttpConnections open to same destination

Lightbeard picture Lightbeard · Dec 20, 2009 · Viewed 16.1k times · Source

We are using HttpURLConnection API to invoke a REST API to the same provider often (kind of an aggregation usecase). We want to keep a pool of 5 connections always open to the provider host (always the same IP).

What is the proper solution? Here is what we tried:


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()));
...

At this point we read the input stream until the BufferedReader returns no more bytes. What do we do after that point if we want to reuse the underlying connection to the provider? We were under the impression that if the input stream is completely read, the connection is then added back to the pool.

It's been working for several weeks this way, but today it stopped working producing this exception: java.net.SocketException: Too many open files

We found numerous sockets in the CLOSE_WAIT state like this (by running lsof): java 1814 root 97u IPv6 844702 TCP colinux:58517->123.123.254.205:www (CLOSE_WAIT)

Won't either conn.getInputStream().close() or conn.disconnect() completely close the connection and remove it from the pool?

Answer

Alexander Torstling picture Alexander Torstling · Dec 20, 2009

From here:

The current implementation doesn't buffer the response body. Which means that the application has to finish reading the response body or call close() to abandon the rest of the response body, in order for that connection to be reused. Furthermore, current implementation will not try block-reading when cleaning up the connection, meaning if the whole response body is not available, the connection will not be reused.

I read this as if your solution should work, but that you are also free to call close and the connection will still be reused.