23

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

5 に答える 5

19

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

ps aux |grep tomcat7

そして、する

cat /proc/1234/limits次のような行を読む

Max open files 16384 16384 files

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

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

于 2015-03-10T15:12:52.970 に答える
11

以下の手順に従って、サーバーの現在の構成をすばやく分析し、Tomcat のハード制限とソフト制限を調整してこの問題を修正してください。

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

ls -l /proc/tomcatPID/fd 

これにより、開いているファイルの数が表示されます。

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

開いているファイルの制限を増やすには update /etc/security/limits.conf

tomcat に固有の開いているファイルの数を確認するには:

ハードリミット:su - tomcat -c 'ulimit -Hn' -s '/bin/bash'

ソフトリミット:su - tomcat -c 'ulimit -Sn' -s '/bin/bash'

以下のスクリプトを corn ジョブで実行して、開いているファイルの詳細を知ることができます。

=============================
#!/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
================= 
于 2017-12-21T13:15:00.877 に答える
10

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

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

sysctl -p次に、シェルで使用して構成をリロードできます。この記事をチェックしてください。

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

于 2014-07-02T15:30:12.763 に答える
4

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

リロードする/etc/security/limits.confには、ログアウトして再度ログインするだけです。

于 2015-11-30T16:04:32.977 に答える
1
  1. このコードがネット操作 (ソケット) からのものである場合、Java XxxxxStrem が OS ファイル制限と 1:1 の関係を持っている (または関係がまったくない) かどうかはわかりません。調査が必要かもしれませんが、例外メッセージのテキストが間違っていますか? ソフトウェアでかなり頻繁に。

  2. 私の直感によると、例外 2 は理解できず、コード (または問題の構成がない) には関係がありません。

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

于 2015-09-09T08:39:39.887 に答える