Best Practice to Use HttpClient in Multithreaded Environment
Asked Answered
N

5

96

For a while, I have been using HttpClient in a multithreaded environment. For every thread, when it initiates a connection, it will create a completely new HttpClient instance.

Recently, I have discovered that, by using this approach, it can cause the user to have too many ports being opened, and most of the connections are in TIME_WAIT state.

http://www.opensubscriber.com/message/[email protected]/86045.html

Hence, instead of each thread doing :

HttpClient c = new HttpClient();
try {
    c.executeMethod(method);
}
catch(...) {
}
finally {
    method.releaseConnection();
}

We plan to have :

[METHOD A]

// global_c is initialized once through
// HttpClient global_c = new HttpClient(new MultiThreadedHttpConnectionManager());

try {
    global_c.executeMethod(method);
}
catch(...) {
}
finally {
    method.releaseConnection();
}

In a normal situation, global_c will be accessed by 50++ threads concurrently. I was wondering, will this create any performance issues? Is MultiThreadedHttpConnectionManager using a lock-free mechanism to implement its thread safe policy?

If 10 threads are using global_c, will the other 40 threads be locked?

Or would it be better if, in every thread, I create an instance of an HttpClient, but release the connection manager explicitly?

[METHOD B]

MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManager();
HttpClient c = new HttpClient(connman);
try {
      c.executeMethod(method);
}
catch(...) {
}
finally {
    method.releaseConnection();
    connman.shutdown();
}

Will connman.shutdown() suffer performance issues?

May I know which method (A or B) is better, for application using an 50++ threads?

Nathanaelnathanial answered 15/8, 2009 at 5:13 Comment(0)
N
18

Method A is recommended by httpclient developer community.

Please refer http://www.mail-archive.com/[email protected]/msg02455.html for more details.

Nathanaelnathanial answered 29/8, 2009 at 15:35 Comment(4)
When will one call "shutdown" on connection manager if client is made global.Penthea
Which tools / linux commands are useful to debug or "visualize" the behavior of the ConnectionManager under the hood? I ask because we currently have trouble with connections in CLOSE_WAIT and other effects and we are strugeling finding a good way to see what is exactly going on.Alphonsa
@WandMaker i'm pretty sure you would just call shutdown when either program exits or when you are finished with some batch of work where you won't need any connections for some time.Monogamy
@Alphonsa netstat does a really nice job at that. technet.microsoft.com/en-us/sysinternals/bb897437.aspx tooMonogamy
S
49

Definitely Method A because its pooled and thread safe.

If you are using httpclient 4.x, the connection manager is called ThreadSafeClientConnManager. See this link for further details (scroll down to "Pooling connection manager"). For example:

    HttpParams params = new BasicHttpParams();
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    ClientConnectionManager cm = new ThreadSafeClientConnManager(params, registry);
    HttpClient client = new DefaultHttpClient(cm, params);
Shawndashawnee answered 23/9, 2010 at 21:11 Comment(5)
ThreadSafeClientConnManager has been deprecated in favor of PoolingClientConnManager in 4.2Ideomotor
Hi, can the httpclient created by this method be used to maintain session as described here #5961332 ...? Because when i tried, i was not able to maintain session across diffrent requests ...Snuck
4.3.1 here: PoolingClientConnManager has been deprecated in favor of PoolingHttpClientConnectionManager.Impossibility
@DrewStephens Again PoolingClientConnManager was deprecatd in favor of PoolingHttpClientConnectionManagerHeavyhanded
@Heavyhanded - Still waiting for PoolingHttpClientConnectionManager to be deprecated before I start my project.Bordello
N
18

Method A is recommended by httpclient developer community.

Please refer http://www.mail-archive.com/[email protected]/msg02455.html for more details.

Nathanaelnathanial answered 29/8, 2009 at 15:35 Comment(4)
When will one call "shutdown" on connection manager if client is made global.Penthea
Which tools / linux commands are useful to debug or "visualize" the behavior of the ConnectionManager under the hood? I ask because we currently have trouble with connections in CLOSE_WAIT and other effects and we are strugeling finding a good way to see what is exactly going on.Alphonsa
@WandMaker i'm pretty sure you would just call shutdown when either program exits or when you are finished with some batch of work where you won't need any connections for some time.Monogamy
@Alphonsa netstat does a really nice job at that. technet.microsoft.com/en-us/sysinternals/bb897437.aspx tooMonogamy
G
13

My reading of the docs is that HttpConnection itself is not treated as thread safe, and hence MultiThreadedHttpConnectionManager provides a reusable pool of HttpConnections, you have a single MultiThreadedHttpConnectionManager shared by all threads and initialised exactly once. So you need a couple of small refinements to option A.

MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManag

Then each thread should be using the sequence for every request, getting a conection from the pool and putting it back on completion of its work - using a finally block may be good. You should also code for the possibility that the pool has no available connections and process the timeout exception.

HttpConnection connection = null
try {
    connection = connman.getConnectionWithTimeout(
                        HostConfiguration hostConfiguration, long timeout) 
    // work
} catch (/*etc*/) {/*etc*/} finally{
    if ( connection != null )
        connman.releaseConnection(connection);
}

As you are using a pool of connections you won't actually be closing the connections and so this should not hit the TIME_WAIT problem. This approach does assuume that each thread doesn't hang on to the connection for long. Note that conman itself is left open.

Gallo answered 15/8, 2009 at 6:9 Comment(1)
Didn't actual answer to my question, on which method (A or B) is better.Nathanaelnathanial
A
7

With HttpClient 4.5 you can do this:

CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(new PoolingHttpClientConnectionManager()).build();

Note that this one implements Closeable (for shutting down of the connection manager).

Autarky answered 9/10, 2017 at 20:0 Comment(0)
E
5

I think you will want to use ThreadSafeClientConnManager.

You can see how it works here: http://foo.jasonhudgins.com/2009/08/http-connection-reuse-in-android.html

Or in the AndroidHttpClient which uses it internally.

Endsley answered 13/8, 2010 at 22:42 Comment(2)
Opps. No plan to migrate from HttpClient 3.x to 4.x, as 3.x had been running flawless in my application for nearly ~2 years :)Nathanaelnathanial
Sure, just if somebody else came here Googling for an answer :)Endsley

© 2022 - 2024 — McMap. All rights reserved.