簡體   English   中英

IOException:打開的文件太多

[英]IOException: Too many open files

我正在嘗試在Linux上的Jetty 7.0.1中運行的Java webapp中調試文件描述符泄漏。

由於打開的文件過多而導致請求開始失敗,應用程序已經愉快地運行了一個月左右,並且必須重新啟動Jetty。

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)

起初我認為問題在於啟動外部程序的代碼,但它使用的是commons-exec ,我沒有看到它有什么問題:

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

在服務器上列出打開的文件我可以看到大量的FIFO:

# 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

當Jetty開始時,只有10個FIFO,幾天之后就有數百個。

我知道在這個階段有點模糊,但你有什么建議在下一步看,或者如何獲得有關這些文件描述符的更詳細的信息?

問題來自您的Java應用程序(或您正在使用的庫)。

首先 ,您應該閱讀整個輸出(Google for StreamGobbler)和pronto!

Javadoc說:

父進程使用這些流向子進程提供輸入並從子進程獲取輸出。 由於某些本機平台僅為標准輸入和輸出流提供有限的緩沖區大小,因此無法及時寫入輸入流或讀取子進程的輸出流可能導致子進程阻塞甚至死鎖。

其次waitFor()你的進程終止。 然后,您應該關閉輸入,輸出和錯誤流。

最后 destroy()你的過程。

我的來源:

當你在Linux上運行時,我懷疑你的文件描述符已經用完了。 查看ulimit。 這篇文章描述了這個問題: http//www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/

您的外部程序行為不正常。 看看它為什么不這樣做。

不知道你的應用程序的性質,但我已經看到這個錯誤多次出現,因為連接池泄漏,所以這是值得檢查。 在Linux上,套接字連接使用文件描述符和文件系統文件。 只是一個想法。

除了查看文件泄漏等根本原因問題,以便合法增加“打開文件”限制並在重新啟動后保持這種限制,請考慮編輯

/etc/security/limits.conf

通過添加這樣的東西

jetty soft nofile 2048
jetty hard nofile 4096

其中“jetty”是這種情況下的用戶名。 有關limits.conf的更多詳細信息,請參閱http://linux.die.net/man/5/limits.conf

注銷然后再次登錄並運行

ulimit -n

驗證更改是否已發生。 此用戶的新流程現在應該符合此更改。 此鏈接似乎描述了如何對已經運行的進程應用限制,但我還沒有嘗試過。

對於大型Java應用程序,默認限制1024可能太低。

你可以自己處理fds。 java中的exec返回一個Process對象。 間歇性地檢查進程是否仍在運行。 一旦完成,關閉進程STDERR,STDIN和STDOUT流(例如proc.getErrorStream.close())。 這將減輕泄漏。

當您同時在許多文件中寫入數據並且操作系統具有固定的Open文件限制時,會出現此問題。 在Linux中,您可以增加打開文件的限制。

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

如何更改Linux中的打開文件數限制?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM