[英]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,幾天之后就有數百個。
我知道在這個階段有點模糊,但你有什么建議在下一步看,或者如何獲得有關這些文件描述符的更詳細的信息?
當你在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/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.