2012-08-14 22 views
4

与此问题密切相关:How to use HttpClient with multithreaded operation?,我在想如果apache HttpAsyncClient是线程安全的,或者它是否也需要使用MultiThreadedHttpConnectionManager或ThreadSafeClientConnManager。如何在多线程操作中使用HttpAsyncClient?

如果确实需要这样的连接管理器,那么存在于异步库中吗?

我能够在异步库中找到PoolingClientAsyncConnectionManager,但我不确定这是否是我需要的。

或者,我正在考虑使用ThreadLocal为每个线程创建一个HttpAsyncClient对象。

请注意,与前面提到的问题不同,我需要状态为独立跨会话,即使多个会话命中同一个域。如果在会话1中设置了cookie,则cookie应该会而不是对会话2可见。出于这个原因,我还考虑为每个请求创建一个全新的HttpAsyncClient对象,尽管我得到的印象应该是更好的方法。

谢谢。

+0

当我想到更多关于它的,我不认为ThreadLocal的正常工作。使用HttpClient,execute方法是阻塞的,但是对于HttpAsyncClient,execute方法是非阻塞的,所以单个线程可能会调用多次执行,这可能会导致与多个线程调用在同一个HttpClient对象上执行相同的干扰。 – Tinclon 2012-08-14 20:10:20

回答

1

负载既没有在PoolingClientAsyncConnectionManager测试之后,我们发现,我们得到的结果不一致的时候,我们没有使用PoolingClientAsyncConnectionManager。除此之外,我们还跟踪了我们正在制作的Http调用的数量,以及已完成的Http调用的数量(通过取消(...),完成(...)或失败(...)。 ..)相关的FutureCallback函数)。如果没有PoolingClientAsyncConnectionManager,并且在负载较重的情况下,这两个数字有时不匹配,导致我们认为某处某些连接跺脚来自其他线程的连接信息(只是猜测)。

无论哪种方式,使用PoolingClientAsyncConnectionManager时,数字总是匹配的,负载测试都是成功的,所以我们肯定会使用它。

我们最终使用的代码是这样的:

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

您提到“独立会话”。如果这只意味着cookies,那么我会认为创建自己的CookieStore,当你的每个线程去使用HttpClient就足够了。

我会使用ThreadLocal创建一个线程客户端,不要使用共享连接管理器,然后积极地清除cookie。这个答案是大约饼干结算有用:

Android HttpClient persistent cookies

类似下面的代码会工作。如果每个请求都是独立的,我已经重写了ThreadLocal.get()方法来调用clear()。您也可以在execute(...)方法中调用清除。

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(); 
    } 
} 
+0

谢谢。这实际上看起来非常接近我已经得到的,除了清除cookie。 然而,cookie的事情只是一个例子。我的意思是我需要每个会议**完全**独立于其他会议。在另一个会话中根本没有数据可见。我需要担心cookies吗? – Tinclon 2012-08-14 19:44:48

+0

我这么认为@Tinclon。以下是一些文档,当他们提到HttpClient状态时,他们似乎只谈论cookie:http://hc.apache.org/httpcomponents-client-ga/tutorial/html/statemgmt.html – Gray 2012-08-14 19:49:21

+0

认证信息是另一件需要担心的事情@Tinclon但只有在您自己设置认证用户名/密码的情况下才有必要。 – Gray 2012-08-14 19:51:20