
测试环境在运行一段时间后出现了too many open files,导致一个定时上报redis的任务频繁失败。
linux默认为1024,可通过ulimit -n命令进行数量调整。
例:ulimit -n 4096
非root用户最大只能设置到4096,需要更多的话需要root权限。
-
执行命令ps -ef | grep java,查出进程id:13945。

-
执行lsof -p 13945
发现有大量的文件句柄没有释放。怀疑是组内小伙伴遍历文件时没有close导致。
于是从代码中寻找蛛丝马迹。
发现原因是delete方法里使用了DirectoryStream并没有close。
java8里的Files.newDirectoryStream(p),通常都使用try(Files.newDirectoryStream()){ } catch() { }的方式,来避免显式close释放资源。
因此判断当时写这段代码的同学看Files.newDirectoryStream()示例时,没看到close()方法误以为不需要释放文件就直接进行使用。导致了too many open files的异常。另外需要注意的是,在try()中打开的文件,不要执行删除操作,否则同样会导致句柄无法释放问题。例如:
try(InputStream inputStream = new FileInputStream(new File(path))) { // doSomething(); } catch(Exception e) { }finally{ Files.deleteIfExists(Paths.get(path)); }会导致如下结果:

文件句柄未释放
总结:
遇到too many open files时, - 执行 lsof -p <pid>,查看该进程打开的句柄
若句柄数不正常,则根据打开的句柄检查不正常的原因,若句柄正常,则进行如下第二步。 -
执行 unlimit -a,查看open files(最大允许打开文件数)

本文介绍了在Linux环境中遇到'TooManyOpenFiles'异常的排查过程。通过`ulimit -n`命令查看并调整文件描述符限制,发现进程ID为13945的Java进程存在大量未关闭的文件句柄。问题根源在于使用了`Files.newDirectoryStream()`但未正确关闭,导致资源泄露。建议使用try-with-resources语句确保文件流的及时关闭,同时注意在try块内不要执行删除操作,以免句柄无法释放。文章强调了正确释放资源和理解API使用的重要性。
https://blog.csdn.net/Clovemeo/article/details/124954657?spm=1001.2014.3001.5501
2160

被折叠的 条评论
为什么被折叠?



