2013-10-28 61 views
12

我有一個應用程序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,但是當我用lsof檢查應用程序的打開文件數量將近200時,爲什麼會發生這種情況,如果它沒有達到極限? 我應該增加限制嗎?是否有任何其他原因得到這個錯誤? 讓服務再次正確運行的唯一方法是重新啓動tomcat,還有另一種恢復正常的方法嗎?

在此先感謝。

編輯: 這裏是處理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: 做一些測試中,我認識到,以後如果我先關閉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()); 
     } 
    } 
} 
+0

是的,我檢查了這個網頁,但作爲服務它也沒有使用超過200的最大值,爲什麼要增加到4096的限制? – alicia

+0

您應該首先在網站上搜索您的錯誤:http://stackoverflow.com/questions/5656458/java-net-socketexception-too-many-open-files – developerwjk

+0

分享您的代碼!我們不能沒有任何代碼片段。 – tokhi

回答

6

這可能是有用的知道,你可以通過添加以下到/etc/security/limits.conf更改打開的文件的限制:

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

然後你就可以重新加載的外殼採用sysctl -p配置。檢查this article

只是爲了完整性您可以驗證什麼是使用打開的文件電流限制:ulimit -n

9

執行以下操作以獲取PID,說1234,tomcat7的

ps aux |grep tomcat7 

,然後做

cat /proc/1234/limits要讀出像下面這樣的一行

Max open files 16384 16384 files

這些是Tomcat允許的最大打開文件數。爲了增加它,請按照以下

Too many open files Tomcat.

+1

我已經檢查並將打開文件的數量增加到不可訪問的數字。我認爲這對應用程序內部的線程來說更糟糕,它可能會是什麼? – alicia

+1

是的,我想你可能在應用程序中泄漏文件處理程序/連接。 – Zouzias

+0

有沒有辦法查看這些打開文件的列表?看看哪個線程打開了它們會很有用。 –

0
  1. 說明如果此代碼是從網上操作(插座),我不知道Java的XxxxxStrem具有1:1關係到OS文件限制(或有關係)。也許需要一些研究,異常信息有錯誤的文字?經常用軟件。

  2. 我的直覺說,我們不理解Exception 2,代碼中沒有任何東西(或者缺失的配置)有關係。

  3. 擴展操作系統文件限制時,軟件錯誤(泄漏)是最主要的問題是糟糕的政策,因爲你瞭解好

2

@gaboroncancio發佈的答案基本上是正確的,但他對如何使建議設置生效並不完全正確。 sysctl -p將重新加載/etc/sysctl.conf或您傳入的任何文件作爲參數。但是,sysctl命令將不會識別/etc/security/limits.conf的格式。

要重新加載/etc/security/limits.conf,你只需要註銷並重新登錄。

+0

是值重新加載需要重新登錄 –

1

這將顯示該進程的所有打開的文件。

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'

您可以在下面的腳本用玉米運行作業知道打開文件的細節。

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

格式化它。 – Billa

相關問題