Tengo 1000 dedicado Java threads donde cada hilo de las encuestas una dirección url correspondiente a cada segundo.

public class Poller { 
    public static Node poll(Node node) { 
        GetMethod method =  null; 
        try { 
            HttpClient client = new HttpClient(new SimpleHttpConnectionManager(true)); 
            ......
        } catch (IOException ex) { 
            ex.printStackTrace(); 
        } finally { 
            method.releaseConnection(); 
        } 
    } 
} 

Los hilos se ejecutan a cada segundo:

for (int i=0; i <1000; i++) { 
    MyThread thread = threads.get(i) //threads  is a static field 
    if(thread.isAlive()) { 
        //If the previous thread is still running, let it run. 
    } else { 
        thread.start(); 
    } 
}

El problema es que si puedo ejecutar el trabajo a cada segundo llego al azar excepciones como estas:

java.net.BindException: Address already in use 
 INFO httpclient.HttpMethodDirector: I/O exception (java.net.BindException) caught when processing request: Address already in use 
 INFO httpclient.HttpMethodDirector: Retrying request 

Pero si puedo ejecutar el trabajo de cada 2 segundos o más, todo funciona bien.

Incluso traté de cerrar la instancia de SimpleHttpConnectionManager() el uso de shutDown (), sin efecto.

Si puedo hacer netstat, veo miles de conexiones TCP en estado TIME_WAIT, lo que significa que se han cerrado y se están limpiando.

Para limitar el número de conexiones, he intentado utilizar una sola instancia de HttpClient y utilizarlo como este:

  public class MyHttpClientFactory { 
        private static MyHttpClientFactory instance = new HttpClientFactory(); 
        private MultiThreadedHttpConnectionManager connectionManager; 
        private HttpClient client; 

        private HttpClientFactory() { 
                init(); 
        } 

        public static HttpClientFactory getInstance() { 
                return instance; 
        } 

        public void init() { 
                connectionManager = new MultiThreadedHttpConnectionManager(); 
                HttpConnectionManagerParams managerParams = new HttpConnectionManagerParams(); 
                managerParams.setMaxTotalConnections(1000); 
                connectionManager.setParams(managerParams); 
                client = new HttpClient(connectionManager); 
        } 

        public HttpClient getHttpClient() { 
                if (client != null) { 
                        return client; 
                } else { 
                    init(); 
                    return client; 
                } 
        } 
}

Sin embargo, después de correr durante exactamente 2 horas, comienza a lanzar «demasiados archivos abiertos’ y, finalmente, no se puede hacer nada en absoluto.

ERROR java.net.SocketException: Too many open files
INFO httpclient.HttpMethodDirector: I/O exception (java.net.SocketException) caught when processing request: Too many open files
INFO httpclient.HttpMethodDirector: Retrying request

Yo debería ser capaz de aumentar el número de conexiones permitidas y hacer que funcione, pero yo sólo sería prolongar el mal. Alguna idea de lo que es la mejor práctica para el uso de HttpClient en una situación como la de arriba?

Por cierto, todavía estoy en HttpClient3.1.

OriginalEl autor Langali | 2010-05-26

3 Comentarios

  1. 3

    Esto que nos pasó hace un par de meses. Primero, verifique para asegurarse de que realmente están llamando releaseConnection() cada vez. Pero incluso entonces, el SO que en realidad no recuperar las conexiones TCP todas a la vez. La solución es utilizar el Apache HTTP del Cliente MultiThreadedHttpConnectionManager. Este piscinas y reutiliza las conexiones.

    Ver http://hc.apache.org/httpclient-3.x/performance.html para obtener más consejos de rendimiento.

    Actualización: ¡Vaya, no he leído el código inferior de la muestra. Si usted está haciendo releaseConnection() y el uso de MultiThreadedHttpConnectionManager, considere si su sistema operativo límite en los archivos abiertos por cada proceso es suficientemente alto. Hemos tenido ese problema, y necesarias para extender el límite un poco.

    Oh, por supuesto, que me enseñan a leer un post completo! Otra cosa a considerar es si tu sistema operativo límite en el número de archivos abiertos por cada proceso es tal vez establecer un poco demasiado bajo. Hemos ampliado nuestro cuando descubrimos que Glassfish estaba usando casi todos los de su asignación a la clase de carga, etc. Que resuelto el problema para nosotros.

    OriginalEl autor Jim Ferrans

  2. 2

    No hay nada de malo con el primer error. Usted acaba agotado empírica de los puertos disponibles. Cada conexión TCP puede permanecer en estado TIME_WAIT durante 2 minutos. Generar 2000/segundos. Más pronto o más tarde, el encaje no puede encontrar la porción de puerto local y obtendrá el error. TIME_WAIT diseñado exactamente para este propósito. Sin ella, el sistema podría secuestrar una conexión anterior.

    El segundo error significa que usted tiene demasiados sockets abiertos. En algunos sistemas, hay un límite de 1K archivos abiertos. Tal vez usted acaba de golpear a ese límite, debido a la persistente tomas de corriente y otros archivos abiertos. En Linux, puede cambiar este límite mediante

      ulimit -n 2048

    Pero que está limitado por un sistema de gran valor máx.

    OriginalEl autor ZZ Coder

  3. 0

    Como sudo o root editar el /etc/security/limits.conf archivo. Al final del archivo, justo encima de «# Fin de Archivo» introduzca los siguientes valores:
    * suave nofile 65535
    * duro nofile 65535
    De esta forma se establecerá el número de archivos abiertos ilimitado.

    OriginalEl autor jacktrade

Dejar respuesta

Please enter your comment!
Please enter your name here