【问题标题】:java.io.FileNotFoundException: /opt/tomcat/conf/tomcat-users.xml (Too many open files)java.io.FileNotFoundException:/opt/tomcat/conf/tomcat-users.xml(打开的文件太多)
【发布时间】:2021-09-20 03:49:28
【问题描述】:

不确定限制设置为 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)

【问题讨论】:

  • 您的 web 应用程序中存在文件描述符泄漏。检查正在打开但未关闭的套接字和文件。将 try-with-resources 撒在 任何地方 以确保它发生。
  • 是在Tomcat启动过程中还是一段时间后出现? tomcat-users.xml 由服务器定期重新加载。我的猜测是:1.服务器达到了打开文件的限制(maxConnections默认是8192,所以超过了操作系统限制),2.Tomcat试图重新加载tomcat-users.xml
  • 一段时间后会发生
  • 不会是 Tomcat 泄露这些资源,而是您的代码。 @PiotrP.Karwasz
  • @user207421:Tomcat 不会泄漏资源,但打开的套接字是 UNIX 上的文件描述符。在我看来,4096 个未关闭的文件比 4096 个并发连接更不可信,尽管两者都可能发生。

标签: java tomcat tomcat9


【解决方案1】:

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

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

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

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

现在扫描 TOMCAT(在我的例子中是 jshell)的 PI​​D:

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

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

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

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

...
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"
}

【讨论】:

    猜你喜欢
    • 2019-05-01
    • 2014-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-09
    • 2016-08-20
    • 2015-06-28
    相关资源
    最近更新 更多