web-dev-qa-db-ja.com

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ですが、lsofを使用してアプリケーションの開いているファイルの数を確認すると、ほぼ200になります。制限を増やすべきですか?このエラーが発生する他の理由はありますか?サービスを再び正しく実行する唯一の方法は、Tomcatを再起動することです。通常の状態に戻す別の方法はありますか?

前もって感謝します。

[〜#〜] edit [〜#〜]:ここに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());
        }
    }
}
20
alicia

Tomcat7のpid(たとえば1234)を取得するには、次の手順を実行します

ps aux |grep Tomcat7

してから

cat /proc/1234/limits次のような行を読み取る

Max open files 16384 16384 files

これらは、Tomcatで許可されるオープンファイルの最大数です。増やすには、以下の手順に従ってください

Tomcatを開いているファイルが多すぎます

13
Zouzias

以下を/etc/security/limits.confに追加することにより、開いているファイルの制限を変更できることを知っておくと便利です。

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

その後、シェルでsysctl -pを使用して構成を再読み込みできます。 この記事 を確認してください。

完全を期すために、次を使用して開いているファイルの現在の制限を確認できます:ulimit -n

9
gaboroncancio

これにより、そのプロセスの開いているすべてのファイルが表示されます。

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
================= 
6

@gaboroncancioが投稿した回答は基本的に正しいですが、設定を有効にする方法に関する彼のアドバイスは正しくありません。 sysctl -pは、/etc/sysctl.conf、または引数として渡したファイルを再ロードします。ただし、sysctlコマンドは/etc/security/limits.confの形式を認識しません。

/etc/security/limits.confをリロードするには、ログアウトして再度ログインする必要があります。

4
lietuviuHimnas
  1. このコードがネットオペレーション(ソケット)からのものである場合、Java XxxxxStremはOSファイルの制限と1対1の関係がある(またはまったく関係がある)かわかりません。メッセージに間違ったテキストが含まれていますか?.

  2. 私の直観では、例外2を理解していないため、コード(または問題のある構成)には何の関係もありません。

  3. ソフトウェアエラー(リーク)が主な問題である場合にOSファイルの制限を拡張することは、よく理解されているように悪いポリシーです

0
Jacek Cz