How to use HttpAsyncClient with multithreaded operation?

Closely related to this question: How to use HttpClient with multi-threaded operation? , I am wondering if apache HttpAsyncClient is thread safe, or if it also requires using MultiThreadedHttpConnectionManager or ThreadSafeClientConnManager.

If it requires such a connection manager, does it exist in asynchronous libraries?

I was able to find the PoolingClientAsyncConnectionManager in asynchronous libraries, but I'm not sure if I need this.

Alternatively, I was thinking about using ThreadLocal to create one HttpAsyncClient object for each thread.

Note that unlike the question I referred to earlier, I need the state to be independent in the sessions, even if multiple sessions fall into the same domain. If the cookie is set in session 1, the cookie should not be visible to session 2. For this reason, I also considered creating a completely new HttpAsyncClient object for each individual request, although I get the impression it should be better.

Thanks.

+4
source share
2 answers

After stress testing with and without the PoolingClientAsyncConnectionManager, we found that we had inconsistent results when we did not use the PoolingClientAsyncConnectionManager.

Among other things, we tracked the number of Http calls that we made and the number of completed Http calls (either through canceled (...), completed (...), or unsuccessful (...) functions of the associated FutureCallback) . Without the PoolingClientAsyncConnectionManager and under heavy load, these two numbers sometimes did not coincide, which led us to believe that somewhere some connections stomped on connection information from other threads (just a hunch).

In any case, with the PoolingClientAsyncConnectionManager, the numbers always match and the load tests were successful, so we definitely use it.

The last code we used is as follows:

public class RequestProcessor { private RequestProcessor instance = new RequestProcessor(); private PoolingClientAsyncConnectionManager pcm = null; private HttpAsyncClient httpAsyncClient = null; private RequestProcessor() { // Initialize the PoolingClientAsyncConnectionManager, and the HttpAsyncClient } public void process(...) { this.httpAsyncClient.execute(httpMethod, new BasicHttpContext(), // Use a separate HttpContext for each request so information is not shared between requests new FutureCallback<HttpResponse>() { @Override public void cancelled() { // Do stuff } @Override public void completed(HttpResponse httpResponse) { // Do stuff } @Override public void failed(Exception e) { // Do stuff } }); } } 
+1
source

You indicate "independently of each other." If that just means cookie, I would think that creating my own CookieStore that clears when each of your streams uses an HttpClient will suffice.

I would use ThreadLocal to create the client on the thread, not use the general connection manager, and then aggressively clear the cookies. This answer was useful when clearing cookies:

Persistent Cookies for Android HttpClient

Something like the following code will work. I redefined the ThreadLocal.get() method to call clear() in case each request is independent. You can also call clear in the execute(...) method.

 private static final ThreadLocal<ClientContext> localHttpContext = new ThreadLocal<ClientContext> () { @Override protected ClientContext initialValue() { return new ClientContext(); } @Override public ClientContext get() { ClientContext clientContext = super.get(); // could do this to clear the context before usage by the thread clientContext.clear(); return clientContext; } }; ... ClientContext clientContext = localHttpContext.get(); // if this wasn't in the get method above // clientContext.clear(); HttpGet httpGet = new HttpGet("http://www.google.com/"); HttpResponse response = clientContext.execute(httpGet); ... private static class ClientContext { final HttpClient httpClient = new DefaultHttpClient(); final CookieStore cookieStore = new BasicCookieStore(); final HttpContext localContext = new BasicHttpContext(); public ClientContext() { // bind cookie store to the local context localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); } public HttpResponse execute(HttpUriRequest request) { // in case you want each execute to be indepedent // clientContext.clear(); return httpClient.execute(request, httpContext); } public void clear() { cookieStore.clear(); } } 
+1
source

All Articles