记录一次生产环境的bug
发生现象

1 | Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool |
开始追踪&&定位问题
根据Redis Too many open files
关键字 搜索到这篇文章
然后就发现对应的java进程使用lsof -p pid
有很多文件夹目录的句柄并没有被释放,如下图

定位代码
在上面的定位到问题之后,开始找项目的代码里面有哪些代码使用到了这些目录,最后就发现类似如下的代码
1 | DirectoryStream<Path> paths = Files.newDirectoryStream(Paths.get(path)); |
看下源码
1 | public static DirectoryStream<Path> newDirectoryStream(Path dir, |
特别地,注意下面的注释
1 | * <p> When not using the try-with-resources construct, then directory |
当没有使用try-with-resources 结构的时候,使用stream的地方必须手动invoke(手动close),用来释放资源.
解决
既然是需要手动close,手动close即可。
手动复现代码
1 | @Test |
总结
大致翻了了java.nio.file.Files的里面的函数newDirectoryStream
都是需要手动close, 另外还有个函数也是需要手动close的 Files.lines
。
所以使用工具函数是可以的,但是也要知其内部实现原理,否则搞不好就是一个定时炸弹