I tried the following example of Apache http client:
http://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientMultiThreadedExecution.java
I set the max pool size as 5 and run ten threads. After running this code, when I check netstat , I see 10 TCP connections being open. I was expecting the connections to be reused. Why is this ? Am I missing something ?
Code snippet is as below:
public class ClientMultiThreadedExecution {
public static void main(String[] args) throws Exception {
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(
new Scheme("http", 18080, PlainSocketFactory.getSocketFactory()));
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(schemeRegistry);
cm.setDefaultMaxPerRoute(5);
cm.setMaxTotal(5);
HttpClient httpclient = new DefaultHttpClient(cm);
try {
// create an array of URIs to perform GETs on
String uri = "http://test.webservice.com:18080/TestServlet";
String data = "This is a test message";
System.out.println("Started at: " + new Date());
// creating 10 threads
PostThread[] threads = new PostThread[10];
for (int i = 0; i < threads.length; i++) {
HttpPost httpPost = new HttpPost(uri);
threads[i] = new PostThread(httpclient, httpPost, data, i + 1);
threads[i].start();
//Thread.sleep(1000);
}
// join the threads
for (int j = 0; j < threads.length; j++) {
threads[j].join();
}
} finally {
// When HttpClient instance is no longer needed,
// shut down the connection manager to ensure
// immediate deallocation of all system resources
System.out.println("Ended at: " + new Date());
httpclient.getConnectionManager().shutdown();
}
}
/**
* A thread that performs a POST.
*/
static class PostThread extends Thread {
private final HttpClient httpClient;
private final HttpContext context;
private final HttpPost httpPost;
private final int id;
private final String data;
public PostThread(HttpClient httpClient, HttpPost httpPost, String data, int id) {
this.httpClient = httpClient;
this.context = new BasicHttpContext();
this.httpPost = httpPost;
this.id = id;
this.data = data;
}
/**
* Executes the PostMethod and prints some status information.
*/
@Override
public void run() {
//System.out.println(id + " - about to get something from " + httpPost.getURI());
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("XML",data));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs,"UTF-8"));
// execute the method
HttpResponse response = httpClient.execute(httpPost, context);
//System.out.println(id + " - get executed");
// get the response body as an array of bytes
if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
System.out.println("Success");
//Is this step necessary ?? Need to check as only status code is required
//httpPost.abort();
//HttpEntity entity = response.getEntity();
//And this ?
//EntityUtils.consume(entity);
} catch (Exception e) {
httpPost.abort();
System.out.println(id + " - error: " + e);
}
}
}}
If you are processing HTTP responses manually instead of using a response handler, you need to close all the http connections by yourself.
From Apache HTTP Client API version 4.3 on wards, DefaultHttpClient is deprecated.
HttpClient is fully thread-safe when used with a thread-safe connection manager such as MultiThreadedHttpConnectionManager.
//Is this step necessary ?? Need to check as only status code is required
//httpPost.abort();
//HttpEntity entity = response.getEntity();
//And this ?
//EntityUtils.consume(entity);
Guess what? It is.
One MUST ensure response content gets consumed in order to have the underlying connection released back to the connection manager. Invocation of either EntityUtils#consume
or httpUriRequest#abort
triggers release of connection back to the pool. The difference is that the former attempts to keep the connection alive while the latter does not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With