2010-09-02 1 views
0

В нашем приложении мы читаем статические ресурсы (то есть файлы JavaScript) из файла jar, расположенного в WEB-INF/lib. Бывает, что сервер завершает работу с исключением too many open files. Я обнаружил (используя lsof), что файл jar открывается несколько раз, и число увеличивается, когда я перезагружаю страницу по количеству файлов JavaScript на странице. Я попробовал пару следующие вещи без положительного результата:Как уменьшить количество открытых дескрипторов файлов в Linux при чтении статических ресурсов из jar-файла в tomcat 6.0?

  • URLConnection setDefaultUSeCache (ложь)
  • URLConnection setUSeCache (ложь)
  • context.xml cachingAllowed = "ложь"

Есть что-то еще я мог попробовать?

+0

Какие рамки веб-приложений вы используете? – Joel

+0

Это домашний каркас. – Michael

ответ

0

Небольшой свет на деталях, но похоже, что вы загружаете ресурсы потоком, поэтому вероятность создания вашего кода также создает анонимный объект в вызове метода (очень распространенная практика в примерах, которые я использую), и я знаю, что это вызывает проблемы с блокировкой файлов в Windows, поэтому я уверен, что он хранит дескрипторы, зависающие в Unix. Убедитесь, что у вас есть блок try, и вы можете вызвать close() в блоке finally, когда закончите. Инструменты анализа статического кода обычно улавливают это условие.

Вы не указали количество ручек файлов, о которых мы говорим. Обычно сетевые подключения будут вашим виновником, и обычно вы хотите увеличить лимит.

1

В сервере Tomcat каждый входящий запрос использует сокет TCP, и этот сокет потребляет один файловый дескриптор из общего количества доступных для процесса. Файл fescriptor (FD) - это дескриптор, созданный процессом при открытии файла. Каждый процесс может использовать заданный предел FD, и обычно это настройка уровня ОС.

Если у вас есть много файлов сценариев JS, загружаемых на страницу, тогда каждый запрос JS будет потреблять один FD во время его обработки.

По мере того, как количество запросов, поступающих на сервер, увеличивается, вы можете столкнуться с ситуацией, когда открыто много сокетов, и, таким образом, у вас закончились FD, и вы получите сообщение «Слишком много открытых файлов».

Проверьте значение # cat /proc/sys/fs/file-max, чтобы узнать, сколько FD может быть открыто вашим Tomcat на сервере.

В идеале должно быть 65535. Смотрите здесь о том, как увеличить этот предел

http://tech-torch.blogspot.com/2009/07/linux-ubuntu-tomcat-too-many-open-files.html

Еще одно предложение, если вы можете уменьшить количество JS вызовов, путем объединения файлов JS в один.

+0

Мне кажется, что вывод lsof показывает обычные файлы в моем случае. Пользователь, который запускает tomcat, может открыть 2048 файлов на процесс. – Michael

0

Входной поток закрыт в блоке finally, как вы предлагаете. Я также посмотрел на URLConnection, но, похоже, нет метода close() или disconnect.

Мне кажется, что файлы были оговорены через определенный промежуток времени. Открытые файлы перечислены lsof, и если я перезагружаю открытые файлы с открытыми страницами вверх. Но через пару минут они снова спускаются. В случае высокого пользовательского трафика дескриптор открытого файла был больше, чем максимум 2048 на процесс. Таким образом, освобождение открытых дескрипторов файлов происходит до конца.

+0

Хм, теперь это точно звучит как объекты, содержащие дескрипторы, собираемые мусором. Я все равно буду искать анонимные связанные объекты ввода-вывода, завернутые в вызовы других методов. Попробуйте Findbugs, он нашел причину подобных проблем в проекте, над которым я работал. http://findbugs.sourceforge.net/ –

+0

Теперь я думаю, что это вызвано вызовами getLastModified(), которые не закрывают InputStream в последнем блоке. Вызывается getLastModified() для целей кэширования, и это также открывает файл каким-либо образом, даже если входной поток не используется впоследствии. В нашем коде поток закрывается только после чтения. – Michael

0

Если написана крошечная тестовая программа, которая открывает URL-соединение с файлом. Он вызывает только getLastModified(), и это уже открывает дескриптор файла.

Впоследствии я закрываю входной поток, и этот эффект исчезает.

Итак, я пришел к выводу, что мне нужно закрыть URLConnection.inputStream, даже если поток не читается после подключения.