简体   繁体   English

tomcat中的错误“打开的文件太多”

[英]Error in tomcat "too many open files"

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?我检查了打开文件的限制,它是 1024,但是当我用 lsof 检查应用程序的打开文件数时,它接近 200,如果没有达到限制,为什么会发生这种情况? 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?让服务再次正常运行的唯一方法是重新启动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?编辑:这是处理 doPost 方法的 servlet,一开始我没有关闭每个流,可能是这样吗? I added the finally statement for doing that:我为此添加了 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). EDIT2:在进行了一些测试之后,我意识到如果我先关闭 DataInputStream 然后关闭 InputStream,我会在消息之前的另一个部分获得一个数字(我不知道为什么)。 I changed the order of closing the stream and it seems that everything it's ok.我更改了关闭流的顺序,似乎一切正常。 But I still have the problem.但我仍然有问题。 Any idea?任何的想法?

  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());
        }
    }
}

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

These are the maximum number of open files that are allowed by Tomcat.这些是 Tomcat 允许的最大打开文件数。 To increase it, follow the instructions below要增加它,请按照以下说明操作

Too many open files Tomcat. Tomcat 打开的文件太多。

Follow the below instructions to have a quick analysis of current configuration with your server and tune the tomcat hard and soft limits to fix this issue.按照以下说明快速分析服务器的当前配置,并调整 tomcat 硬限制和软限制以解决此问题。

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/security/limits.conf .增加打开文件限制更新/etc/security/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 $2}')
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,$11 "" >> "/usr/local/files_report.txt"}')
echo "--------------------`date`---Ending  Session ------------------------------" >> /usr/local/files_report.txt
fi
================= 

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.然后您可以在 shell 上使用sysctl -p重新加载配置。 Checkthis article .检查这篇文章

Just for completeness you can verify what is the current limit for opened files using: ulimit -n为了完整起见,您可以使用以下命令验证打开文件的当前限制: ulimit -n

The answer @gaboroncancio posted is basically correct, but his advice on how to make the settings take effect is not quite right. @gaboroncancio 发布的答案基本正确,但他关于如何使设置生效的建议不太正确。 sysctl -p will reload /etc/sysctl.conf , or whatever file you pass in as an argument. sysctl -p将重新加载/etc/sysctl.conf或您作为参数传入的任何文件。 However, the sysctl command will not recognize the format of /etc/security/limits.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 ,您只需要注销并重新登录。

  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).如果此代码来自网络操作(套接字),我不确定 Java XxxxxStrem 与 OS 文件限制有 1:1 的关系(或根本没有关系)。 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.我的直觉说,我们不理解异常 2,代码中的任何内容(或没有问题的配置)都没有关系。

  3. Extending OS files limit when software error (leak) is main problem is bad policy, as You good understand当软件错误(泄漏)是主要问题时扩展操作系统文件限制是不好的政策,正如您所理解的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM