【发布时间】:2012-02-03 05:36:34
【问题描述】:
我正在开发一个相当复杂的 Web 应用程序,它调用几个外部执行的进程、一个 grails 后台进程以及读取/写入多个文件 - 所有这些都在一个控制器中。一切都很好,直到我用近距离的许多请求对其进行了测试。当我这样做时,我在我的 tomcat catalina 日志文件中收到以下 java 错误消息:
WARNING: Exception executing accept
java.net.SocketException: Too many open files
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)
at java.net.ServerSocket.implAccept(ServerSocket.java:462)
at java.net.ServerSocket.accept(ServerSocket.java:430)
at org.apache.jk.common.ChannelSocket.accept(ChannelSocket.java:312)
at org.apache.jk.common.ChannelSocket.acceptConnections(ChannelSocket.java:666)
at org.apache.jk.common.ChannelSocket$SocketAcceptor.runIt(ChannelSocket.java:877)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
at java.lang.Thread.run(Thread.java:662)
起初,经过一番愉快的谷歌搜索和阅读后,我怀疑这可能是一个“系统问题”,即我必须提高执行 tomcat 的用户的打开文件限制 - 但事实并非如此。
然后我开始阅读很多关于 Java 的建议,而不是关于 Grails 和 Groovy 的建议,因为如果你在谷歌上搜索 Grails 的这个问题,你找不到那么多。我现在怀疑我的问题是由“打开的流太多”(或类似的东西)引起的,而不是实际打开的文件太多(因为打开的文件数量实际上并没有那么大)。
我在一个闭包中有很多以下四种类型的操作:
1) 打开文件并写入:
def someFile = new File("/some/file.txt")
someFile << "Some content\n"
2) 执行命令:
def cmd = "bash some-cmd".execute()
cmd.waitFor()
3) 从文件中读取内容:
def fileContent = new File("/some/file.txt").text
4) 从网络上的文件中读取内容:
def URL url = new URL("http://www.some.link");
def URLConnection uc = url.openConnection()
def BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream()))
...
br.close()
如您所见,我唯一明确关闭的是带有 InputStream 的 BufferedReader,我相信 br.close() 会同时关闭它们。
我是否必须关闭任何其他打开的连接,或者更好:我可以这样做吗?执行此操作的命令是什么?还是您认为我的问题真的不是由“被遗忘的开放流”引起的?
我的问题主要来源于Why do I get "Too many open files" errors?和IOException: Too many open files的答案。
我正在使用 grails 1.1.1(我知道它已经过时了,但是我在将应用程序迁移到当前版本时遇到了严重的问题,经过数小时的工作我放弃了它),groovy 1.8.0,tomcat 6.0。 28,ubuntu 10.10 上的 apache 2.2.16。
解决我的“打开的文件太多”问题的答案与 Stephen C 的答案非常相关。似乎我的错误的第一个原因确实是未关闭的 BufferedReader Stream。我基本上将他的 java-code 建议直接转移到了 grails:
def URL url = new URL("http://www.some.link");
def URLConnection uc = url.openConnection()
def BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream()))
try{
...
}finally{
br.close()
}
-> 这绝对解决了“打开的文件太多”的问题,我现在什至可以看到问题的真正根源。
【问题讨论】:
-
几天前我遇到了与 UrlConnection 类似的问题。我通过阅读流的全部内容来解决它。
-
嗯...您能否详细说明一下,即给我一个简短的代码示例?不过,我不确定这是否真的能解决我的问题。我使用 BufferedReader/URLConnection 的目的是在将一个非常大的文件(最大 1 GB)传输到我的服务器之前,只检查其头部是否有正确的文件格式。
-
我暂时无法访问代码,但我可以稍后发布...
标签: java file tomcat grails groovy