2011-04-13 25 views
13

Tengo una aplicación java que funciona bien (en Ubuntu 10.04) durante unas horas hasta que golpea "java.net.SocketException: Demasiados archivos abiertos". El código para Sender.java se puede encontrar herejava.net.SocketException: Demasiados archivos abiertos

¿Es porque creo una nueva instancia de HttpPut y HttpPost para cada hilo? Estoy usando Apache Commons HTTPClient 4.

Aquí está el registro de excepciones:

java.net.SocketException: Too many open files 
    at java.net.Socket.createImpl(Socket.java:414) 
    at java.net.Socket.connect(Socket.java:544) 
    at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:123) 
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:133) 
    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149) 
    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:108) 
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554) 
    at com.marketplace.io.Sender.doBasicHttpPost(Sender.java:434) 
    at com.marketplace.io.Sender.appVisualExists(Sender.java:223) 
    at com.marketplace.io.Sender.addVisualToCollection(Sender.java:350) 
    at com.marketplace.service.ImageThread.run(ImageThread.java:136) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:166) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) 
    at java.lang.Thread.run(Thread.java:636) 
+0

¿Alguna vez se apaga el httpclient.? –

+1

No tengo tiempo para revisar todo el código (lo siento), pero parece que (continuamente) no cierras las conexiones que abres. –

+0

@The Elite Gentleman- No, yo no. No estoy seguro de cómo hacer eso. Parte de la documentación para HTTPClient es inexistente. – Raunak

Respuesta

10

En la línea 438 que presentamos lo mejor la respuesta como una corriente y convertir eso a una matriz de bytes. El InputStream devuelto por entity.getContent() no se cierra. Esto podría estar contribuyendo al problema. Además, el HttpEntity.consumeContent() está en desuso por motivos relacionados.

+0

Gracias por entrar en problemas y mirar el código fuente. Voy a dejar el código funcionando durante la noche y ver si los cambios sugeridos hacen alguna diferencia. – Raunak

+2

No estoy seguro de qué solucionó el problema; si era httpClient.getConnectionManager(). shutdown(); o tu sugerencia Gracias por tu ayuda. – Raunak

7

Es posible que también desee comprobar el límite máximo de archivos abiertos de Linux. Este related link es para un producto a medida basado en Java pero explica muy bien los pasos necesarios para solucionar el problema.

+1

Y, una definición del término técnico más molesto desde 'nube': http://www.techterms.com/definition/bespoke –

+5

¿Puedo obtener puntos de reputación por el uso correcto de términos molestos? ;) – DrUseful

2

(RESUELTO)

recientemente Tengo el mismo error porque el var/log en la Base de Datos servidor está lleno.

#df -h 
S.ficheros   Size Used Avail Use% Montado en 

/dev/cciss/c0d0p3  126G 126G 0G 100% /var 


#echo "">/var/log/postgresql/postgresql.log 

¡Ahora, el error ya no existe!

importante: ver lo que iniciar postgresql.log, revisar su postgresql.conf

bye
@_jpgo

11

"java.net.SocketException: Demasiados archivos abiertos" se puede ver cualquiera de Java Aplicación de servidor, por ejemplo Tomcat, Weblogic, WebSphere, etc., con clientes que se conectan y desconectan con frecuencia.

Tenga en cuenta que las conexiones de socket se tratan como archivos y utilizan el descriptor de archivo, que es un recurso limitado.

El sistema operativo diferente tiene diferentes límites en la cantidad de identificadores de archivos que pueden administrar.

En resumen, este error viene porque los clientes se están conectando y desconectando frequently.If desea manejar por su lado, tiene dos opciones:

1) Aumentar el número de identificadores de archivo abierto o descriptores de fichero por proceso.

En sistema operativo basado en UNIX, p. Ubuntu o Solaris, puede usar el comando ulimit -a para averiguar cuántos manejos de archivos abiertos por proceso está permitido.

$ ulimit -a 
core file size  (blocks, -c) unlimited 
data seg size   (kbytes, -d) unlimited 
file size    (blocks, -f) unlimited 
open files     (-n) 256 
pipe size   (512 bytes, -p) 10 
stack size   (kbytes, -s) 8192 
cpu time    (seconds, -t) unlimited 
max user processes   (-u) 2048 
virtual memory  (kbytes, -v) unlimited 

Se puede ver que, archivos abiertos (-n) 256, lo que significa que sólo 256 de archivo abierto se permite por proceso. Si su programa Java, recuerde Tomcat, weblogic o cualquier otro servidor de aplicaciones son programas Java y se ejecutan en JVM, excede este límite, arrojará java.net.SocketException: Demasiados archivos abren el error.

Puede cambiar este límite utilizando ulimit -n a un número mayor, p. Ej.4096, pero hágalo con el asesoramiento del administrador del sistema UNIX y si tiene un equipo de soporte de UNIX por separado, que escalarán mejor a ellos.

2) Reducir el tiempo de espera para el estado TIME_WAIT en su sistema operativo

En sistemas basados ​​en UNIX, se puede ver la configuración actual en /proc/sys/net/ipv4/tcp_fin_timeout archivo.

En el sistema basado en Windows, puede ver esta información en el registro de Windows. Se puede cambiar el tiempo de espera TCPTIME_WAIT en Windows siguiendo los pasos siguientes:

1) Open Windows Registry Editor, by typing regedit in run command window 
2) Find the key HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\tcpip\Parameters 
3) Add a new key value pair TcpTimedWaitDelay asa decimal and set the desired timeout in seconds (60-240) 
4) Restart your windows machine. 
+0

Utilicé root para iniciar sesión y ejecutar estos comandos. Pero cuando cambié a otro usuario ordinario, encontré que el número de archivos abiertos no había sido cambiado. ¿Podría configurar el número de identificadores de archivos abiertos para todos los usuarios? – niaomingjian

+0

Verifique su configuración por: tail -f /etc/security/limits.conf. Asegúrese de que los cambios se hayan guardado para que se puedan aplicar a todos los usuarios –

+0

Con la verificación de la configuración por: ulimit -n, parece que se ha cambiado de 1024 a 4096 (después de ejecutar ulimit -n 4096). Pero por la cola -f /etc/security/limits.conf, encontré que no hay ningún cambio en el archivo. – niaomingjian

0

resuelvo el problema mediante el cierre de la conexión en el bloque finally

public static String postMethod(String jsonStr,String sendUrl){ 
    String resultJson = ""; 
    HttpClient httpClient = new HttpClient(); 
    PostMethod post = new PostMethod(sendUrl); 
    post.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8"); 
    NameValuePair[] param = { new NameValuePair("message",jsonStr)} ; 
    post.setRequestBody(param); 
    try { 
     httpClient.executeMethod(post); 
     resultJson = post.getResponseBodyAsString(); 
    } catch (HttpException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    }finally{ 
     post.releaseConnection(); 
     ((SimpleHttpConnectionManager)httpClient.getHttpConnectionManager()).shutdown(); 
    } 
    return resultJson; 
} 
Cuestiones relacionadas