./log-error-2023-05-05.0.log:java.io.FileNotFoundException: /tmp/tomcat.8054.6662226014931657024/work/Tomcat/localhost/ROOT/upload_2de0ae12_86e7_49cd_b138_fc8af49b7a59_00006179.tmp (打开的文件过多)

服务突然宕机 出现这个错误

打开的文件过多,一般来说是由于应用程序对资源使用不当造成,比如没有及时关闭Socket或数据库连接等。但也可能应用确实需要打开比较多的文件句柄,而系统本身的设置限制了这一数量。

过程

最开始还以为是linux文件数不不够,不停的调整文件打开大小

查看系统允许打开的最大文件数

#cat /proc/sys/fs/file-max

查看每个用户允许打开的最大文件数
ulimit -a
发现系统默认的是open files (-n) 1024,问题就出现在这里。

在系统文件/etc/security/limits.conf中修改这个数量限制,在文件中加入内容:

* soft nofile 65536 
* hard nofile 65536
* soft nproc 65536
* hard nproc 65536
* soft  memlock  unlimited
* hard memlock  unlimited

或只加下面两个参数都行的
* soft nofile 65536 
* hard nofile 65536
修改完成保存,重启服务器

错误

异常1:
12-Jun-2018 01:30:15.340 严重 [http-nio-8080-Acceptor-0] org.apache.tomcat.util.net.NioEndpoint$Acceptor.run Socket accept failed
 java.io.IOException: 打开的文件过多
	at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
	at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)
	at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
	at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:453)
	at java.lang.Thread.run(Thread.java:748)

异常二
java.net.SocketException: Too many open files

    at java.net.PlainSocketImpl.accept(Compiled Code) 
    at java.net.ServerSocket.implAccept(Compiled Code) 
    at java.net.ServerSocket.accept(Compiled Code) 
    at weblogic.t3.srvr.ListenThread.run(Compiled Code) 
	
第一个异常则在错误影响到 I/O 操作时抛出,而第二个异常在错误影响到基础 TCP 协议时抛出。

分析

  1. 可能是tomcat文件
    /tmp/tomcat.8054.6662226014931657024/work/Tomcat/localhost 说明是这个目录下的文件找不到了,后来经过查资料,tmp的文件10天之内不访问就会删除,所以可能是这个原因,调整tomcat的日志路径
#tomcat
server.tomcat.basedir=/home/tomcatlog
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern= '%h %l %u %t "%r" %s %b %D %{User-Agent}i'
  1. 使用命令lsof -p 进程id可以查看单个进程所有打开的文件详情,使用命令lsof -p 进程id | wc -l可以统计进程打开了多少文件:

查看进程打开的文件

lsof -p 31878

发现大量文件

Java new File中如果存在null则找不到文件 java filenotfound_linux

改成静态

Java new File中如果存在null则找不到文件 java filenotfound_.net_02


lsof -p 1305 | wc -l 查看当前进程id为1305的 文件操作状况

  1. 如果你对你的程序有一定的解的话,应该对程序打开文件数(链接数)上限有一定的估算,如果感觉数字异常,请使用第一步的lsof -p 进程id > openfiles.log命令,获得当前占用句柄的全部详情进行分析,

1)打开的这些文件是不是都是必要的?
2)定位到打开这些文件的代码
3)是否程序操作了文件写入,但是没有进行正常关闭
4)是否程序进行了通讯,但是没有正常关闭(也就是没有超时结束的机制)

实战

崩溃的原因 文件打开过多,解决方案:
lsof -p 19945 | wc -l 进程pid为19945的文件打开数
lsof -p 19945 进程的文件打开详情

之前设置的各种文件打开最大数限制好像并未生效,文件数到4096就开始报错了

Java new File中如果存在null则找不到文件 java filenotfound_tomcat_03


后来使用arthas查到了jvm打开最大文件数是4096

Java new File中如果存在null则找不到文件 java filenotfound_服务器_04


MAX-FILE-DESCRIPTOR-COUNT:JVM 进程最大可以打开的文件描述符数

OPEN-FILE-DESCRIPTOR-COUNT:JVM 当前打开的文件描述符数找到对应代码之后,使用postman调用,每次调用文件打开数就会+1,查找到内存泄露的代码后,改完,再次使用postman调用,文件打开数不再明显增长

Java new File中如果存在null则找不到文件 java filenotfound_.net_05


Java new File中如果存在null则找不到文件 java filenotfound_tomcat_06