我的java进程的文件描述符变“坏”了,我不知道为什么

2022-09-03 08:10:29

我有一个Java webapp,用Lucene构建,我不断得到各种“文件已经关闭”的异常 - 取决于我使用的目录实现。我已经能够从Lucene中获取“java.io.IOException Bad File Descriptor”和“java.nio.channels.ClosedChannelException”,通常包裹在IndexReader的已经关闭的Exception中。

有趣的是,我还没有关闭IndexReader,似乎文件描述符本身就过时了。我使用的是最新版本的Lucene 3.0(还没有时间从3.0系列中升级),最新版本的Oracle的JDK6,最新版本的Tomcat 6和最新版本的CentOS。我可以在其他Linux系统上使用相同的软件复制该错误,但不能在Windows系统上复制该错误,并且我没有OSX PC可以测试。Linux服务器是用qEmu虚拟化的,如果这很重要的话。

这似乎也与负载有关 - 发生这种情况的频率对应于Tomcat(对此特定Web应用程序)提供的请求/秒数。例如,在一台服务器上,每个请求都按预期完成,直到它必须处理 ~2 reqs/sec,然后大约 10% 的请求在请求开始时从它们下面开始关闭其文件描述符(代码检查有效的 IndexReader 对象,并在处理请求开始时创建一个对象)。一旦达到大约3 reqs /秒,所有请求都开始失败,文件描述符错误。

我最好的猜测是,不知何故,在操作系统级别存在资源匮乏,操作系统正在清理fds...但这仅仅是因为我已经消除了我所经历过的所有其他想法。我已经检查了ulimits和文件系统fd限制,并且打开描述符的数量远低于任何一个限制(示例输出来自:1020 0 203404,ulimit -n:10240)。sysctl fs.file-nr

我几乎完全没有要测试的东西,我并没有比我发现它的那一天更接近解决这个问题。有没有人经历过类似的事情?

编辑07 / 12 / 2011:我发现一台OSX机器用于一些测试,并确认这种情况发生在OSX上。我还在物理Linux机器上进行了测试并复制了该问题,因此我无法复制此问题的唯一操作系统是Windows。我猜这与POSIX处理文件描述符有关,因为这似乎是两个测试系统之间唯一相关的区别(JDK版本,tomcat版本和webapp在所有平台上都是相同的)。


答案 1

你可能没有在Windows上看到这种情况发生的原因可能是它的FSDirectory.open默认使用SimpleFSDirectory。

查看FSDirectory和NIOFSDirectory顶部的警告:http://lucene.apache.org/java/3_3_0/api/core/org/apache/lucene/store/NIOFSDirectory.html 处的红色文本:

注意:如果线程在 IO 上被阻塞,则在线程中断时直接或间接地从该类访问该类可以立即关闭基础文件描述符。文件描述符将保持关闭状态,随后对 NIOFSDirectory 的访问将引发 ClosedChannelException。如果你的应用程序使用 Thread.interrupt() 或 Future.cancel(布尔值),你应该使用 SimpleFSDirectory 来支持 NIOFSDirectory。

https://issues.apache.org/jira/browse/LUCENE-2239


答案 2

推荐