Ошибка в tomcat "слишком много открытых файлов"

У меня есть приложение, работающее на 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)

Я проверяю пределы открытых файлов и 1024, но когда я проверяю количество открытых файлов приложения, если он почти 200, почему это происходит, если оно не достигает предела? Должен ли я увеличить лимит? Есть ли другая причина для получения этой ошибки? Единственный способ снова запустить службу снова, перезапустив tomcat, есть ли другой способ вернуться к нормальной работе?

Спасибо заранее.

ИЗМЕНИТЬ: Вот сервлет, который обрабатывает метод doPost, в начале я не закрывал каждый поток, не так ли? Я добавил выражение 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: После некоторого тестирования я понимаю, что если я закрою сначала 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());
        }
    }
}

Ответ 1

Сделайте следующее, чтобы получить pid, скажем 1234, tomcat7

ps aux |grep tomcat7

а затем do

cat /proc/1234/limits, чтобы прочитать строку, такую ​​как

Max open files 16384 16384 files

Это максимальное количество открытых файлов, разрешенных Tomcat. Чтобы увеличить его, следуйте инструкциям ниже

Слишком много открытых файлов Tomcat.

Ответ 2

Может быть полезно знать, что вы можете изменить предел открытых файлов, добавив следующее к /etc/security/limits.conf:

* soft nofile 2048 # Set the limit according to your needs
* hard nofile 2048

Затем вы можете перезагрузить конфигурацию, используя sysctl -p в оболочке. Проверьте эту статью.

Просто для полноты вы можете проверить, каков текущий предел для открытых файлов, используя: ulimit -n

Ответ 3

Ответ @gaboroncancio опубликован в основном правильно, но его советы о том, как сделать настройки вступили в силу, не совсем правильные. sysctl -p перезагрузит /etc/sysctl.conf или любой другой файл, который вы передадите в качестве аргумента. Однако команда sysctl не распознает формат /etc/security/limits.conf.

Чтобы перезагрузить /etc/security/limits.conf, вам просто нужно выйти и войти в систему.

Ответ 4

  • Если этот код из сетевых операций (сокетов), я не уверен, что Java XxxxxStrem имеет отношение 1:1 к ограничениям файла ОС (или имеет отношение вообще). Может быть, нужно какое-то исследование, сообщение об ошибке имеет неправильный текст? Довольно часто в программном обеспечении.

  • Моя интуиция говорит, что мы не понимаем Exception 2, ничто в коде (или в отсутствии конфигурации) не имеет отношения.

  • Расширение ограничений файлов ОС, когда ошибка программного обеспечения (утечка) является основной проблемой, - это плохая политика, так как вы хорошо понимаете

Ответ 5

Это отобразит все открытые файлы этого процесса.

ls -l /proc/tomcatPID/fd 

Это покажет количество открытых файлов.

ls -l /proc/tomcatPID/fd | wc -l 

Чтобы увеличить ограничение на обновление открытых файлов /etc/Secirity/limits.conf.

Чтобы проверить отсутствие открытых файлов, специфичных для tomcat:

Жесткий предел: su - tomcat -c 'ulimit -Hn' -s '/bin/bash'

Мягкий предел: su - tomcat -c 'ulimit -Sn' -s '/bin/bash'

Вы можете запустить ниже script с заданием кукурузы, чтобы узнать подробности открытых файлов.

=============================
#!/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
=================