5

この質問に密接に関連しています: How to use HttpClient with multithreaded operation? 、Apache HttpAsyncClient がスレッドセーフなのか、それとも MultiThreadedHttpConnectionManager または ThreadSafeClientConnManager を使用する必要があるのか​​ 疑問に思っています。

そのような接続マネージャーが必要な場合、非同期ライブラリに存在しますか?

非同期ライブラリで PoolingClientAsyncConnectionManager を見つけることができましたが、それが必要かどうかはわかりません。

または、ThreadLocal を使用して、スレッドごとに 1 つの HttpAsyncClient オブジェクトを作成することを考えていました。

以前に参照した質問とは異なり、複数のセッションが同じドメインにヒットした場合でも、状態がセッション間で独立している必要があることに注意してください。セッション 1 で Cookie が設定されている場合、セッション 2 には Cookieが表示されないようにする必要があります。このため、リクエストごとにまったく新しい HttpAsyncClient オブジェクトを作成することも検討しましたが、より良い方法があるはずです。 .

ありがとう。

4

2 に答える 2

2

あなたは「セッション間で独立している」と言っています。これが単にCookieを意味する場合CookieStoreは、各スレッドがaを使用するときにクリアされる独自のCookieを作成するHttpClientだけで十分だと思います。

ThreadLocalスレッドごとのクライアントを作成するために使用し、共有接続マネージャーを使用せずに、Cookieを積極的にクリアします。この回答は、Cookieのクリアに役立ちました。

AndroidHttpClient永続的なCookie

次のコードのようなものが機能します。各リクエストが独立している場合ThreadLocal.get()に呼び出すメソッドをオーバーライドしました。メソッドclear()で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();
    }
}
于 2012-08-14T19:29:28.697 に答える
1

PoolingClientAsyncConnectionManager を使用した場合と使用しない場合の両方で負荷テストを行った結果、PoolingClientAsyncConnectionManager を使用しなかった場合に一貫性のない結果が得られることがわかりました。

特に、作成中の Http 呼び出しの数と、完了した Http 呼び出しの数 (cancel(...)、completed(...)、または failed(...) 関数のいずれかを介して) を追跡しました。関連する FutureCallback の)。PoolingClientAsyncConnectionManager がなく、負荷が高い場合、2 つの数値が一致しないことがあり、どこかで、一部の接続が他のスレッドからの接続情報を踏みにじっていると思われます (推測にすぎません)。

いずれにせよ、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
      }
    });
  }
}
于 2012-11-10T05:58:59.553 に答える