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:
Este problema se produce cuando escribe datos en muchos archivos simultáneamente y su sistema operativo tiene un límite fijo de archivos abiertos. En Linux, puede aumentar el límite de archivos abiertos.
https://www.tecmint.com/increase-set-open-file-limits-in-linux/
¿Cómo cambio el número de límite de archivos abiertos en Linux?
Mientras se ejecuta en Linux, sospecho que se está quedando sin descriptores de archivos. Echa un vistazo a ulimit. Aquí hay un artículo que describe el problema: http://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/
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.