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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 19:00:41  来源:igfitidea点击:

Error in tomcat "too many open files"

javatomcatservletstomcat7

提问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 -pon 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/limitsto 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 允许的最大打开文件数。要增加它,请按照以下说明操作

Too many open files Tomcat.

Tomcat 打开的文件太多。

回答by Jacek Cz

  1. 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.

  2. My intuition say, we don't understand Exception 2, nothing in code (or configuration absent in question) has relation.

  3. Extending OS files limit when software error (leak) is main problem is bad policy, as You good understand

  1. 如果此代码来自网络操作(套接字),我不确定 Java XxxxxStrem 与 OS 文件限制有 1:1 的关系(或根本没有关系)。也许需要一些研究,异常消息有错误的文本?经常在软件中。

  2. 我的直觉说,我们不理解异常 2,代码中的任何内容(或没有问题的配置)都没有关系。

  3. 当软件错误(泄漏)是主要问题时扩展操作系统文件限制是不好的政策,正如您所理解的

回答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 -pwill reload /etc/sysctl.conf, or whatever file you pass in as an argument. However, the sysctlcommand 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
=================