Mejor práctica utilizar HttpClient en entorno de multiproceso
-
16-09-2019 - |
Pregunta
Durante un tiempo, he estado usando HttpClient en un entorno multiproceso. Por cada hilo, cuando se inicia una conexión, se creará una nueva instancia HttpClient.
Recientemente, he descubierto que, mediante el uso de este enfoque, puede causar que el usuario tenga demasiados puertos se abren, y la mayoría de las conexiones se encuentran en estado TIME_WAIT.
http: //www.opensubscriber. com/message/commons-httpclient-dev@jakarta.apache.org/86045.html
Por lo tanto, en lugar de cada uno haciendo hilo:
HttpClient c = new HttpClient();
try {
c.executeMethod(method);
}
catch(...) {
}
finally {
method.releaseConnection();
}
planea tener:
[procedimiento A]
// global_c is initialized once through
// HttpClient global_c = new HttpClient(new MultiThreadedHttpConnectionManager());
try {
global_c.executeMethod(method);
}
catch(...) {
}
finally {
method.releaseConnection();
}
En una situación normal, global_c se accederá por 50 ++ hilos al mismo tiempo. Me preguntaba, ¿esto crear ningún problema de rendimiento? Se MultiThreadedHttpConnectionManager utilizando un mecanismo libre de bloqueo para aplicar su política de seguridad hilo?
se bloquearáSi 10 hilos están utilizando global_c, los otros 40 hilos?
O sería mejor si, en cada hilo, se crea una instancia de un HttpClient, pero la autorización del administrador de conexión de forma explícita?
[procedimiento B]
MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManager();
HttpClient c = new HttpClient(connman);
try {
c.executeMethod(method);
}
catch(...) {
}
finally {
method.releaseConnection();
connman.shutdown();
}
¿Se connman.shutdown () sufren problemas de rendimiento?
se puede saber qué método (A o B) es mejor, para la aplicación utilizando un 50 ++ hilos?
Solución 2
Método A es recomendada por httpclient comunidad de desarrolladores.
Por favor, consulte http: //www.mail- archive.com/httpclient-users@hc.apache.org/msg02455.html para más detalles.
Otros consejos
Definitivamente Método A porque su agruparon y seguro para subprocesos.
Si está utilizando 4.x httpclient, el administrador de conexión se llama ThreadSafeClientConnManager . Ver este enlace rel="noreferrer"> para más detalles (desplazarse hacia abajo para " La puesta en común de gestión de conexiones "). Por ejemplo:
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);
Mi lectura de los documentos es que HttpConnection sí mismo no es tratado como hilo de seguridad, y por lo tanto ofrece una piscina MultiThreadedHttpConnectionManager reutilizable de HttpConnections, que tiene un único MultiThreadedHttpConnectionManager compartida por todas las discusiones y inicializado exactamente una vez. Así que hay un par de pequeñas mejoras a la opción A.
MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManag
A continuación, cada uno de ellos hay que utilizar la secuencia para cada solicitud, para conseguir una conexión desde la piscina y volver a colocarlo en la terminación de su trabajo - con ayuda de un bloque finally puede ser bueno. También debe código para la posibilidad de que la piscina no tiene conexiones disponibles y procesar la excepción de tiempo de espera.
HttpConnection connection = null
try {
connection = connman.getConnectionWithTimeout(
HostConfiguration hostConfiguration, long timeout)
// work
} catch (/*etc*/) {/*etc*/} finally{
if ( connection != null )
connman.releaseConnection(connection);
}
Como está utilizando un conjunto de conexiones que no se realiza ningún cerrando las conexiones y por lo tanto esto no debe golpear el problema TIME_WAIT. Este enfoque hace assuume que cada hilo no se aferran a la conexión por mucho tiempo. Tenga en cuenta que en sí estafador se deja abierta.
Creo que tendrá que usar ThreadSafeClientConnManager.
Puede ver cómo funciona aquí: http: //foo.jasonhudgins.com/2009/08/http-connection-reuse-in-android.html
O en el AndroidHttpClient
que utiliza internamente.
Con HttpClient 4.5 se puede hacer esto:
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(new PoolingHttpClientConnectionManager()).build();
Tenga en cuenta que éste implementa se puede cerrar (para el cierre del administrador de conexión).