too open many increase files descriptors java linux jetty ioexception file-descriptor

increase - too many open files java



IOException: demasiados archivos abiertos (7)

Estoy intentando depurar una fuga de descriptor de archivo en una aplicación web de Java que se ejecuta en Jetty 7.0.1 en Linux.

La aplicación se ejecutó felizmente durante aproximadamente un mes cuando las solicitudes empezaron a fallar debido a demasiados archivos abiertos , y Jetty tuvo que reiniciarse.

java.io.IOException: Cannot run program [external program]: java.io.IOException: error=24, Too many open files at java.lang.ProcessBuilder.start(ProcessBuilder.java:459) at java.lang.Runtime.exec(Runtime.java:593) at org.apache.commons.exec.launcher.Java13CommandLauncher.exec(Java13CommandLauncher.java:58) at org.apache.commons.exec.DefaultExecutor.launch(DefaultExecutor.java:246)

Al principio pensé que el problema estaba relacionado con el código que inicia el programa externo, pero está usando commons-exec y no veo nada de malo en ello:

CommandLine command = new CommandLine("/path/to/command") .addArgument("..."); ByteArrayOutputStream errorBuffer = new ByteArrayOutputStream(); Executor executor = new DefaultExecutor(); executor.setWatchdog(new ExecuteWatchdog(PROCESS_TIMEOUT)); executor.setStreamHandler(new PumpStreamHandler(null, errorBuffer)); try { executor.execute(command); } catch (ExecuteException executeException) { if (executeException.getExitValue() == EXIT_CODE_TIMEOUT) { throw new MyCommandException("timeout"); } else { throw new MyCommandException(errorBuffer.toString("UTF-8")); } }

Al listar archivos abiertos en el servidor, puedo ver una gran cantidad de FIFOs:

# lsof -u jetty ... java 524 jetty 218w FIFO 0,6 0t0 19404236 pipe java 524 jetty 219r FIFO 0,6 0t0 19404008 pipe java 524 jetty 220r FIFO 0,6 0t0 19404237 pipe java 524 jetty 222r FIFO 0,6 0t0 19404238 pipe

cuando Jetty comienza, solo hay 10 FIFOs, después de unos días hay cientos de ellos.

Sé que es un poco vago en esta etapa, pero ¿tiene alguna sugerencia sobre dónde buscar a continuación o cómo obtener información más detallada sobre esos descriptores de archivo?


Además de buscar problemas de causa raíz, como fugas de archivos, etc., para hacer un aumento legítimo del límite de "archivos abiertos" y hacer que esto persista en los reinicios, considere editar

/etc/security/limits.conf

añadiendo algo como esto

jetty soft nofile 2048 jetty hard nofile 4096

donde "embarcadero" es el nombre de usuario en este caso. Para obtener más detalles sobre limits.conf, consulte http://linux.die.net/man/5/limits.conf

cerrar sesión y luego volver a iniciar sesión y ejecutar

ulimit -n

Para verificar que el cambio ha tenido lugar. Los nuevos procesos de este usuario ahora deberían cumplir con este cambio. Este enlace parece describir cómo aplicar el límite a los procesos que ya están en ejecución, pero no lo he probado.

El límite predeterminado 1024 puede ser demasiado bajo para aplicaciones Java grandes.


El problema proviene de su aplicación Java (o de una biblioteca que está usando).

Primero , debes leer todos los resultados (Google para StreamGobbler), y pronto!

Javadoc dice:

El proceso principal utiliza estas secuencias para alimentar la entrada y obtener la salida del subproceso. Debido a que algunas plataformas nativas solo proporcionan un tamaño de búfer limitado para los flujos de entrada y salida estándar, el hecho de no escribir rápidamente el flujo de entrada o leer el flujo de salida del subproceso puede hacer que el subproceso se bloquee, e incluso el interbloqueo.

En segundo lugar , waitFor() su proceso para terminar. A continuación, debe cerrar los flujos de entrada, salida y error.

Finalmente destroy() tu Proceso.

Mis fuentes:




No sé la naturaleza de su aplicación, pero he visto este error manifestarse varias veces debido a una fuga en el grupo de conexiones, por lo que valdría la pena echarle un vistazo. En Linux, las conexiones de socket consumen descriptores de archivo así como archivos de sistema de archivos. Solo un pensamiento.


Su programa externo no se comporta correctamente. Echa un vistazo a por qué no hace eso.


Usted puede manejar los fds usted mismo. El exec en java devuelve un objeto de proceso. Compruebe intermitentemente si el proceso todavía se está ejecutando. Una vez que se haya completado, cierre los procesos STDERR, STDIN y STDOUT streams (por ejemplo, proc.getErrorStream.close ()). Eso mitigará las fugas.