wake-up-neo.com

IOException: Zu viele offene Dateien

Ich versuche, ein Dateideskriptordefizit in einer Java-Webapp zu debuggen, das in Jetty 7.0.1 unter Linux ausgeführt wird.

Die App wurde seit ungefähr einem Monat glücklich ausgeführt, als Anforderungen aufgrund von zu vielen geöffneten Dateien fehlschlugen, und Jetty musste neu gestartet werden.

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)

Zuerst dachte ich, das Problem war mit dem Code, der das externe Programm startet, aber es verwendet commons-exec und ich sehe nichts Falsches daran:

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"));
    }
}

Offene Dateien auf dem Server auflisten Ich kann eine hohe Anzahl von FIFOs sehen:

# 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

wenn Jetty startet, gibt es nur 10 FIFOs, nach ein paar Tagen gibt es hunderte von ihnen.

Ich weiß, dass es zu diesem Zeitpunkt etwas vage ist, aber haben Sie Vorschläge, wo Sie als nächstes suchen müssen oder wie Sie detailliertere Informationen über diese Dateideskriptoren erhalten können?

25
Mirko N.

Ihr externes Programm verhält sich nicht richtig. Schau dir an, warum es das nicht tut.

Das Problem stammt von Ihrer Java-Anwendung (oder einer verwendeten Bibliothek).

Zuerst sollten Sie die gesamten Ausgaben (Google für StreamGobbler) lesen und pronto!

Javadoc sagt:

Der übergeordnete Prozess verwendet diese Streams Eingabe für und __ Ausgabe von der unterprozess. Weil einige native Plattformen bieten nur einen begrenzten Puffer Größe für Standardeingabe und -ausgabe Streams, Fehler beim sofortigen Schreiben der Eingabestrom oder Lesen des Ausgabestroms des Unterprozesses kann dazu führen, dass zu blockierender Unterprozess und sogar Sackgasse.

Zweitens, waitFor() Ihr Prozess zum Beenden . Sie sollten dann die Eingabe-, Ausgabe- und Fehlerströme schließen.

Schließlichdestroy() / Ihren Prozess.

Meine Quellen:

24
ofavre

Da Sie unter Linux laufen, vermute ich, dass Ihnen die Dateideskriptoren ausgehen. Schauen Sie sich ulimit an. Hier ist ein Artikel, der das Problem beschreibt: http://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/

8
Greg Smith

Abgesehen von den Hauptursachenproblemen wie Dateilecks usw., sollten Sie die Bearbeitung in Betracht ziehen, um die Grenze für "offene Dateien" zu erhöhen

/etc/security/limits.conf

indem Sie so etwas hinzufügen

jetty soft nofile 2048
jetty hard nofile 4096

dabei ist "Jetty" der Benutzername. Weitere Informationen zu limits.conf finden Sie unter http://linux.die.net/man/5/limits.conf

abmelden und erneut anmelden und ausführen

ulimit -n

um zu überprüfen, ob die Änderung stattgefunden hat. Neue Prozesse dieses Benutzers sollten dieser Änderung jetzt entsprechen. Dieser Link scheint zu beschreiben, wie das Limit auf bereits laufende Prozesse angewendet wird, aber ich habe es nicht ausprobiert.

Das Standardlimit 1024 kann für große Java-Anwendungen zu niedrig sein.

5
Rami Jaamour

Sie kennen nicht die Art Ihrer App, aber ich habe gesehen, dass dieser Fehler mehrmals aufgrund eines Verbindungspool-Lecks aufgetreten ist, so dass es sich lohnt, dies zu überprüfen. Unter Linux verbrauchen Socket-Verbindungen Dateibeschreibungen sowie Dateisystemdateien. Nur ein Gedanke.

5
alasdairg

Sie können die FDS selbst handhaben. Der Exec in Java gibt ein Process-Objekt zurück. Prüfen Sie gelegentlich, ob der Prozess noch läuft. Schließen Sie anschließend die Prozesse STDERR, STDIN und STDOUT (z. B. proc.getErrorStream.close ()). Das wird die Leckagen mildern.

2
allenjsomb

Dieses Problem tritt auf, wenn Sie Daten in viele Dateien gleichzeitig schreiben und Ihr Betriebssystem eine feste Anzahl von offenen Dateien hat. In Linux können Sie das Limit für offene Dateien erhöhen.

https://www.tecmint.com/increase-set-open-file-limits-in-linux/

Wie ändere ich die Anzahl offener Dateien in Linux?

0
Vpn_talent