我有一个 Java 应用程序可以正常运行(在 Ubuntu 10.04 上)几个小时,直到它出现“java.net.SocketException:打开的文件太多”。可以找到 Sender.java 的代码 here
是因为我为每个线程创建了一个新的HttpPut
和HttpPost
实例吗?我正在使用 apache-commons HTTPClient 4。
这是异常日志:
java.net.SocketException: Too many open files
at java.net.Socket.createImpl(Socket.java:414)
at java.net.Socket.connect(Socket.java:544)
at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:123)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:133)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:108)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554)
at com.marketplace.io.Sender.doBasicHttpPost(Sender.java:434)
at com.marketplace.io.Sender.appVisualExists(Sender.java:223)
at com.marketplace.io.Sender.addVisualToCollection(Sender.java:350)
at com.marketplace.service.ImageThread.run(ImageThread.java:136)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:636)
最佳答案
“java.net.SocketException:打开的文件太多”可以在任何 Java 服务器应用程序中看到,例如Tomcat、Weblogic、WebSphere 等,客户端连接和断开连接频繁。
请注意,套接字连接被视为文件,它们使用文件描述符,这是一种有限的资源。
不同的操作系统对它们可以管理的文件句柄数量有不同的限制。
简而言之,出现此错误是因为客户端连接和断开连接频繁。如果您想自己处理,您有两种选择:
1) 增加每个进程打开的文件句柄或文件描述符的数量。
在基于 UNIX 的操作系统中,例如Ubuntu 或 Solaris,您可以使用命令 ulimit -a 来查明每个进程允许打开多少个文件句柄。
$ ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
open files (-n) 256
pipe size (512 bytes, -p) 10
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 2048
virtual memory (kbytes, -v) unlimited
可以看到,open files (-n) 256,这意味着每个进程只允许打开 256 个文件句柄。如果您的 Java 程序,记住 Tomcat、weblogic 或任何其他应用程序服务器是 Java 程序并且它们在 JVM 上运行,超过此限制,它将抛出 java.net.SocketException:打开的文件太多错误。
您可以使用 ulimit -n 将此限制更改为更大的数字,例如4096,但请听取 UNIX 系统管理员的建议,如果您有单独的 UNIX 支持团队,最好上报给他们。
2) 减少操作系统中 TIME_WAIT 状态的超时
在基于 UNIX 的系统中,您可以在 /proc/sys/net/ipv4/tcp_fin_timeout 文件中查看当前配置。
在基于 Windows 的系统中,您可以在 Windows 注册表中看到此信息。您可以按照以下步骤更改 Windows 中的 TCPTIME_WAIT 超时:
1) Open Windows Registry Editor, by typing regedit in run command window
2) Find the key HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\tcpip\Parameters
3) Add a new key value pair TcpTimedWaitDelay asa decimal and set the desired timeout in seconds (60-240)
4) Restart your windows machine.
关于java.net.SocketException : Too many open files 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5656458/