Pergunta

Por um tempo, tenho vindo a utilizar HttpClient em um ambiente multithread. Para cada segmento, quando se inicia uma conexão, ele irá criar uma nova instância HttpClient.

Recentemente, eu descobri que, usando esta abordagem, pode fazer com que o usuário tenha muitas portas se abriram, e a maioria das conexões estão no estado TIME_WAIT.

http: //www.opensubscriber. com/message/commons-httpclient-dev@jakarta.apache.org/86045.html

Assim, em vez de cada thread fazendo:

HttpClient c = new HttpClient();
try {
    c.executeMethod(method);
}
catch(...) {
}
finally {
    method.releaseConnection();
}

Nós planejamos 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();
}

Numa situação normal, global_c vai ser acedida por 50 ++ threads simultaneamente. Eu estava pensando, isso vai criar problemas de desempenho? MultiThreadedHttpConnectionManager está usando um mecanismo de livre-lock para implementar sua política de thread-safe?

Se 10 tópicos estão usando global_c, será que os outros 40 threads ser bloqueado?

Ou seria melhor se, em cada segmento, eu criar uma instância de um HttpClient, mas liberar 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();
}

Will connman.shutdown () sofrem problemas de desempenho?

Posso saber qual o método (A ou B) é melhor, para aplicação usando um 50 ++ tópicos?

Foi útil?

Solução 2

Método A é recomendado por httpclient comunidade de desenvolvedores.

Por favor, consulte http: //www.mail- archive.com/httpclient-users@hc.apache.org/msg02455.html para mais detalhes.

Outras dicas

Definitivamente Método A porque a sua agrupados e thread-safe.

Se você estiver usando httpclient 4.x, o gerenciador de conexões é chamado ThreadSafeClientConnManager . Veja este ligação para mais detalhes (desça até " pooling gerenciador de conexões "). Por exemplo:

    HttpParams params = new BasicHttpParams();
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    ClientConnectionManager cm = new ThreadSafeClientConnManager(params, registry);
    HttpClient client = new DefaultHttpClient(cm, params);

A minha leitura dos docs é que HttpConnection si não é tratado como thread-safe, e, portanto, MultiThreadedHttpConnectionManager fornece uma piscina reutilizável de HttpConnections, você tem um único MultiThreadedHttpConnectionManager compartilhado por todas as threads e inicializado exatamente uma vez. Então você precisa de um par de pequenos refinamentos a opção A.

MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManag

Em seguida, cada segmento deve estar usando a seqüência para cada pedido, recebendo uma conexão a partir da piscina e colocá-lo de volta no final dos seus trabalhos - usando um bloco, finalmente, pode ser bom. Você também deve código para a possibilidade de que a piscina não tem 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 que você não vai realmente ser fechar as conexões e por isso este não deve bater o problema TIME_WAIT. Esta abordagem faz assuume que cada segmento não pendurar a conexão por muito tempo. Note-se que em si conman é deixada em aberto.

Eu acho que você vai querer usar ThreadSafeClientConnManager.

Você pode ver como ele funciona aqui: http: //foo.jasonhudgins.com/2009/08/http-connection-reuse-in-android.html

Ou no AndroidHttpClient que usa-lo internamente.

Com HttpClient 4,5 você pode fazer isso:

CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(new PoolingHttpClientConnectionManager()).build();

Note que esta implementos closeable (para desligar do gerenciador de conexões).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top