首页 > 解决方案 > java.io.FileNotFoundException:/opt/tomcat/conf/tomcat-users.xml(打开的文件太多)

问题描述

不确定限​​制设置为 4096 可能有什么问题,我正在使用 Apache Tomcat/9.0.26 我认为扩展限制不是一个选项,因为问题出在 tomcat-users.xml

tomcat-users.xml:

<GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>
20-Sep-2021 03:20:15.225 WARNING [Catalina-utility-1] org.apache.catalina.users.MemoryUserDatabase.backgroundProcess Failed to close [conf/tomcat-users.xml]
    java.io.FileNotFoundException: /opt/tomcat/conf/tomcat-users.xml (Too many open files)
        at java.io.FileInputStream.open0(Native Method)
        at java.io.FileInputStream.open(FileInputStream.java:195)
        at java.io.FileInputStream.<init>(FileInputStream.java:138)
        at java.io.FileInputStream.<init>(FileInputStream.java:93)
        at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:90)
        at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:188)
        at org.apache.catalina.users.MemoryUserDatabase.backgroundProcess(MemoryUserDatabase.java:685)
        at org.apache.catalina.realm.UserDatabaseRealm.backgroundProcess(UserDatabaseRealm.java:143)
        at org.apache.catalina.realm.CombinedRealm.backgroundProcess(CombinedRealm.java:299)
        at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1137)
        at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1353)
        at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1335)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)
20-Sep-2021 03:20:16.017 SEVERE [http-nio-8080-Acceptor] org.apache.tomcat.util.net.Acceptor.run Socket accept failed
    java.io.IOException: Too many open files
        at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
        at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:419)
        at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:247)
        at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:463)
        at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:73)
        at org.apache.tomcat.util.net.Acceptor.run(Acceptor.java:95)
        at java.lang.Thread.run(Thread.java:748)

标签: javatomcattomcat9

解决方案


这很可能是由于您的一个或多个 web 应用程序中的资源管理不善,或者系统负载很高而默认文件句柄限制太低造成的。

在 Linux 和 Unix 操作系统上,您可以通过检查打开的文件句柄来进行初步调查,lsof并查看打开文件的名称是否存在特定模式 - 这可能会将您指向未使用 try-with- 的特定 Web 应用程序资源在使用后正确关闭文件句柄。

这是一个示例 - 这里我模拟了我使用 jshell 设置的文件处理问题,但您需要检查您的 Tomcat 实例:

jshell
jshell> var outputstream = new FileOutputStream(new File("this-is-open.txt"))
outputstream ==> java.io.FileOutputStream@4d76f3f8

现在扫描 TOMCAT 的 PID(在我的例子中是 jshell):

ps -ef |grep java 
# or find the correct JVM from this list:
jps

为上面的 pid运行lsofgrep 并查看它是否报告进程的异常打开文件活动。

lsof | grep 167 |more   # replace "167" by PID FOR YOUR PROCESS

在长长的列表中的某处,您会看到“this-is-open.txt”。请注意,对于 JVM,尤其是 TOMCAT,在任何给定时间都会有许多有效的打开文件句柄,包括您的 tomcat 服务器的 jar、共享库等。您正在寻找可能会提醒您自己的应用程序使用的名称的名称(例如临时输出或处理文件名)。

...
java  167  myuser  9w REG  0,14  0 66146619527007160 /mnt/c/temp/this-is-open.txt

当您发现问题时,请使用代码标准进行修复,以便使用 try 块自动管理所有资源:

try(var autoclosed = blah) {
    // do something with "autoclosed"
}

推荐阅读