Por um tempo, tenho usado HttpClient em um ambiente multithread. Para cada thread, quando ele inicia uma conexão, ele criará uma instância HttpClient completamente nova.
Recentemente, descobri que, usando essa abordagem, pode fazer com que o usuário tenha muitas portas sendo abertas, e a maioria das conexões estão no estado TIME_WAIT.
http://www.opensubscriber.com/message/[email protected]/86045.html
Portanto, em vez de cada thread fazer:
HttpClient c = new HttpClient();
try {
c.executeMethod(method);
}
catch(...) {
}
finally {
method.releaseConnection();
}
Pretendemos ter:
[MÉTODO A]
// global_c is initialized once through
// HttpClient global_c = new HttpClient(new MultiThreadedHttpConnectionManager());
try {
global_c.executeMethod(method);
}
catch(...) {
}
finally {
method.releaseConnection();
}
Em uma situação normal, global_c será acessado por 50 ++ threads simultaneamente. Eu queria saber, isso criará problemas de desempenho? O MultiThreadedHttpConnectionManager está usando um mecanismo sem bloqueio para implementar sua política de thread-safe?
Se 10 threads estiverem usando global_c, as outras 40 threads serão bloqueadas?
Ou seria melhor se, em cada thread, eu criasse uma instância de um HttpClient, mas liberasse o gerenciador de conexões explicitamente?
[MÉTODO B]
MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManager();
HttpClient c = new HttpClient(connman);
try {
c.executeMethod(method);
}
catch(...) {
}
finally {
method.releaseConnection();
connman.shutdown();
}
O connman.shutdown () sofrerá problemas de desempenho?
Posso saber qual método (A ou B) é melhor, para aplicativos que usam threads de 50 ++?
fonte
O método A é recomendado pela comunidade de desenvolvedores httpclient.
Consulte http://www.mail-archive.com/[email protected]/msg02455.html para obter mais detalhes.
fonte
netstat
faz um ótimo trabalho nisso. technet.microsoft.com/en-us/sysinternals/bb897437.aspx tambémMinha leitura dos documentos é que HttpConnection em si não é tratado como thread-safe e, portanto, MultiThreadedHttpConnectionManager fornece um pool reutilizável de HttpConnections, você tem um único MultiThreadedHttpConnectionManager compartilhado por todos os threads e inicializado exatamente uma vez. Portanto, você precisa de alguns pequenos refinamentos para a opção A.
MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManag
Então, cada thread deve usar a sequência para cada solicitação, obter uma conexão do pool e colocá-la de volta na conclusão de seu trabalho - usar um bloco finally pode ser bom. Você também deve codificar a possibilidade de que o pool não tenha conexões disponíveis e processar a exceção de tempo limite.
HttpConnection connection = null try { connection = connman.getConnectionWithTimeout( HostConfiguration hostConfiguration, long timeout) // work } catch (/*etc*/) {/*etc*/} finally{ if ( connection != null ) connman.releaseConnection(connection); }
Como você está usando um pool de conexões, não estará realmente fechando as conexões e, portanto, não deve ocorrer o problema TIME_WAIT. Essa abordagem pressupõe que cada thread não se agarra à conexão por muito tempo. Observe que o próprio conman fica aberto.
fonte
Acho que você vai querer usar ThreadSafeClientConnManager.
Você pode ver como funciona aqui: http://foo.jasonhudgins.com/2009/08/http-connection-reuse-in-android.html
Ou no
AndroidHttpClient
qual o utiliza internamente.fonte
Com o HttpClient 4.5, você pode fazer isso:
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(new PoolingHttpClientConnectionManager()).build();
Observe que este implementa Closeable (para desligar o gerenciador de conexões).
fonte