Мои дескрипторы файла java-процесса идут "плохо", и я понятия не имею, почему

У меня есть java webapp, построенный с Lucene, и я продолжаю получать различные "закрытые файлы" исключений - в зависимости от того, какую директорию я использую. Я смог получить "java.io.IOException Bad File Descriptor" и "java.nio.channels.ClosedChannelException" из Lucene, обычно обернутый вокруг AlreadyClosedException для IndexReader.

Самое смешное, что я не закрыл IndexReader, и кажется, что дескрипторы файлов сами по себе устарели. Я использую последнюю версию Lucene 3.0 (не успели обновиться из серии 3.0), последнюю версию Oracle JDK6, последнюю версию Tomcat 6 и последнюю версию CentOS. Я могу воспроизвести ошибку с тем же программным обеспечением в других системах Linux, но не в системах Windows, и у меня нет компьютера OSX для тестирования. Серверы linux виртуализируются с помощью qEmu, если это вообще может иметь значение.

Это, по-видимому, также связано с нагрузкой - как часто это происходит, соответствует количеству запросов/секунд, которые обслуживает Tomcat (к этому конкретному webapp). Например, на одном сервере каждый запрос завершается так, как ожидалось, до тех пор, пока он не будет иметь дело с ~ 2 reqs/sec, тогда около 10% начнут сбрасывать свои дескрипторы файлов из-под них, средний запрос (код проверяет действительный объект IndexReader и создает один в начале обработки запроса). После того, как он достигнет порядка 3 reqs/sec, все запросы начнут с ошибкой с файловыми дескрипторами.

Моя лучшая догадка заключается в том, что каким-то образом существует голод на ресурсах на уровне ОС, а ОС очищает fds... но это просто потому, что я устранил все остальные идеи, которые у меня были. Я уже проверял ulimits и ограничения файловой системы fd, а количество открытых дескрипторов значительно ниже любого предела (пример выводится из sysctl fs.file-nr: 1020 0 203404, ulimit -n: 10240).

Я почти полностью неспособен проверить, и я не ближе к решению этого, чем тот день, когда я узнал об этом. Кто-нибудь испытал что-то подобное?

EDIT 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(boolean), вы должны использовать SimpleFSDirectory в пользу NIOFSDirectory

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