Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to keep multiple Java HttpConnections open to same destination

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?

like image 712
Lightbeard Avatar asked Dec 20 '09 20:12

Lightbeard


People also ask

What is HTTP connection pooling?

When you set up connection pooling, instead of closing the client HTTP connection after use, CICS keeps the connection open and stores it in a pool in a dormant state. The dormant connection can be reused by the same application or by another application that connects to the same host and port.

What is Max connections per route?

By default, the maximum number of connections is 20 and the maximum connection number per route is 2. However, these values are generally too low for real-world applications. For example, when all the connections are busy with handling other requests, HttpClient won't create a new connection if the number exceeds 20.

How long can a HTTP connection last?

In Firefox, the number of simultaneous connections can be customized (per-server, per-proxy, total). Persistent connections time out after 115 seconds (1.92 minutes) of inactivity which is changeable via the configuration.

How does PoolingHttpClientConnectionManager work?

The PoolingHttpClientConnectionManager will create and manage a pool of connections for each route or target host we use. The default size of the pool of concurrent connections that can be open by the manager is two for each route or target host and 20 for total open connections. Notice the EntityUtils.


2 Answers

We had this problem also on Java 5 and our solution is to switch to Apache HttpClient with pooled connection manager.

The keepalive implementation of Sun's URL handler for HTTP is very buggy. There is no maintenance thread to close idle connections.

Another bigger problem with keepalive is that you need to delete responses. Otherwise, the connection will be orphaned also. Most people don't handle error stream correctly. Please see my answer to this question for an example on how to read error responses correctly,

HttpURLConnection.getResponseCode() returns -1 on second invocation

like image 169
ZZ Coder Avatar answered Sep 28 '22 07:09

ZZ Coder


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.

like image 39
Alexander Torstling Avatar answered Sep 28 '22 09:09

Alexander Torstling