Ошибка в 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
=================