Java tomcat中的错误“打开的文件太多”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19636676/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Error in tomcat "too many open files"
提问by alicia
I have an application running on tomcat and sometimes I have the error below:
我有一个在 tomcat 上运行的应用程序,有时会出现以下错误:
SEVERE: Socket accept failed
java.net.SocketException: Too many open files
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398)
at java.net.ServerSocket.implAccept(ServerSocket.java:522)
at java.net.ServerSocket.accept(ServerSocket.java:490)
at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:60)
at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:216)
at java.lang.Thread.run(Thread.java:722)
....
....
SEVERE: Error processed default web.xml named conf/web.xml at /local/myApp/apache-tomcat/conf/web.xml
java.io.FileNotFoundException: /local/myApp/apache-tomcat/conf/web.xml (Too many open files)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at org.apache.catalina.startup.ContextConfig.getWebXmlSource(ContextConfig.java:1838)
at org.apache.catalina.startup.ContextConfig.getGlobalWebXmlSource(ContextConfig.java:1745)
at org.apache.catalina.startup.ContextConfig.getDefaultWebXmlFragment(ContextConfig.java:1418)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1253)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:878)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:369)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5269)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.StandardContext.reload(StandardContext.java:3926)
at org.apache.catalina.loader.WebappLoader.backgroundProcess(WebappLoader.java:426)
at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1345)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1530)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1540)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1540)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1519)
at java.lang.Thread.run(Thread.java:722)
I check the limits of the open files and it's 1024 but when I check the number of open files of the application with lsof it's nearly 200, why this happen if it does not reach the limit? Should I increase the limit? Is there any other reason to get this error? The only way to get the service running correctly again, it's restarting the tomcat, is there another way of getting back to normal?
我检查了打开文件的限制,它是 1024,但是当我用 lsof 检查应用程序的打开文件数时,它接近 200,如果没有达到限制,为什么会发生这种情况?我应该增加限额吗?是否有其他原因导致此错误?让服务再次正常运行的唯一方法是重新启动tomcat,还有其他恢复正常的方法吗?
Thanks in advance.
提前致谢。
EDIT: Here is the servlet which process the doPost method, at the beginning I didn't close every stream, could it be that? I added the finally statement for doing that:
编辑:这是处理 doPost 方法的 servlet,一开始我没有关闭每个流,可能是这样吗?我为此添加了 finally 语句:
InputStream is = null;
DataInputStream dis = null;
OutputStream os = null;
DataOutputStream dos = null;
String paramName = "";
try {
os = response.getOutputStream();
is = request.getInputStream();
dis = new DataInputStream(is);
dos = new DataOutputStream(os);
.....
}catch (Throwable e) {
LOGGER.error(e.getMessage());
} finally {
if (dis != null) {
dis.close();
}
else if(is != null) {
is.close();
}
if (dos != null) {
dos.close();
}
else if( os != null) {
os.close();
}
}
EDIT2:After making some testing I realize that if I close first the DataInputStream and then the InputStream, I get in the other part of the communication a number before the message(I don't know why). I changed the order of closing the stream and it seems that everything it's ok. But I still have the problem. Any idea?
EDIT2:在进行了一些测试之后,我意识到如果我先关闭 DataInputStream 然后关闭 InputStream,我会在消息之前的另一个部分获得一个数字(我不知道为什么)。我更改了关闭流的顺序,似乎一切正常。但我仍然有问题。任何的想法?
finally {
if(is != null) {
try {
is.close();
} catch (IOException e) {
LOGGER.error(e.getMessage());
}
}
if (dis != null) {
try {
dis.close();
} catch (IOException e) {
LOGGER.error(e.getMessage());
}
}
if(os != null) {
try {
os.close();
} catch (IOException e) {
LOGGER.error(e.getMessage());
}
}
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
LOGGER.error(e.getMessage());
}
}
}
回答by gaboroncancio
It may be useful to know that you can change the limit of opened files by adding the following to /etc/security/limits.conf
:
知道您可以通过将以下内容添加到 来更改打开文件的限制可能很有用/etc/security/limits.conf
:
* soft nofile 2048 # Set the limit according to your needs
* hard nofile 2048
Then you can reload the configuration using sysctl -p
on the shell. Check this article.
然后您可以sysctl -p
在 shell 上使用重新加载配置。检查这篇文章。
Just for completeness you can verify what is the current limit for opened files using: ulimit -n
为了完整起见,您可以使用以下方法验证打开文件的当前限制: ulimit -n
回答by Zouzias
Do the following to get the pid, say 1234, of tomcat7
执行以下操作以获取 tomcat7 的 pid,例如 1234
ps aux |grep tomcat7
and then do
然后做
cat /proc/1234/limits
to read a line like the following
cat /proc/1234/limits
阅读如下一行
Max open files 16384 16384 files
Max open files 16384 16384 files
These are the maximum number of open files that are allowed by Tomcat. To increase it, follow the instructions below
这些是 Tomcat 允许的最大打开文件数。要增加它,请按照以下说明操作
回答by Jacek Cz
If this code is from net operations (sockets), I'm not sure Java XxxxxStrem has 1:1 relation to OS file limits (or has relation at all). Maybe need some research, exception message has wrong text? Quite often in software.
My intuition say, we don't understand Exception 2, nothing in code (or configuration absent in question) has relation.
Extending OS files limit when software error (leak) is main problem is bad policy, as You good understand
如果此代码来自网络操作(套接字),我不确定 Java XxxxxStrem 与 OS 文件限制有 1:1 的关系(或根本没有关系)。也许需要一些研究,异常消息有错误的文本?经常在软件中。
我的直觉说,我们不理解异常 2,代码中的任何内容(或没有问题的配置)都没有关系。
当软件错误(泄漏)是主要问题时扩展操作系统文件限制是不好的政策,正如您所理解的
回答by lietuviuHimnas
The answer @gaboroncancio posted is basically correct, but his advice on how to make the settings take effect is not quite right. sysctl -p
will reload /etc/sysctl.conf
, or whatever file you pass in as an argument. However, the sysctl
command will not recognize the format of /etc/security/limits.conf
.
@gaboroncancio 发布的答案基本正确,但他关于如何使设置生效的建议不太正确。sysctl -p
将重新加载/etc/sysctl.conf
,或您作为参数传入的任何文件。但是,该sysctl
命令将无法识别/etc/security/limits.conf
.
To reload /etc/security/limits.conf
, you just need to log out and log back in.
要重新加载/etc/security/limits.conf
,您只需要注销并重新登录。
回答by krishna garikapati
This will display all open files of that process.
这将显示该进程的所有打开文件。
ls -l /proc/tomcatPID/fd
This will show the count of open files.
这将显示打开文件的数量。
ls -l /proc/tomcatPID/fd | wc -l
To increase open files limit update /etc/Secirity/limits.conf
.
增加打开文件限制更新/etc/Secirity/limits.conf
。
To check no of open files specific to tomcat:
要检查没有特定于 tomcat 的打开文件:
Hard limit : su - tomcat -c 'ulimit -Hn' -s '/bin/bash'
硬限制: su - tomcat -c 'ulimit -Hn' -s '/bin/bash'
Soft limit : su - tomcat -c 'ulimit -Sn' -s '/bin/bash'
软限制: su - tomcat -c 'ulimit -Sn' -s '/bin/bash'
You can run below script with a corn job to know the details of open files.
您可以使用玉米作业运行以下脚本以了解打开文件的详细信息。
=============================
#!/bin/bash
PID=$(ps -ef|grep tomcat6|grep -v grep |awk '{print }')
value=$(ls -l /proc/$PID/fd | wc -l)
echo `date`@$PID:$value >> /usr/local/filecount.txt
if [ $value -gt 2000 ];
then
printf "\n\n\n\n\n" >> /usr/local/files_report.txt
echo "-------------------------------`date`--Starting Session----------------------" >> /usr/local/files_report.txt
openfiles=$(ls -l /proc/$PID/fd | awk '{print NR, "" >> "/usr/local/files_report.txt"}')
echo "--------------------`date`---Ending Session ------------------------------" >> /usr/local/files_report.txt
fi
=================