Слишком много открытых файлов (Mono .NET в Ubuntu) - PullRequest
5 голосов
/ 24 января 2012

Я знаю, что в SO много вопросов, но я не вижу ничего, что соответствует моей конкретной ситуации.

Я запускаю консольное приложение .NET через Mono в Ubuntu.Приложение работает как сервер и принимает соединения через TcpListener (TcpListener.AcceptTcpClient ()).У меня проблема в том, что через некоторое время программа начинает выдавать исключения «Слишком много открытых файлов».

Я увеличил максимальный лимит файлов в Ubuntu в двух местах, которые мне известны:

  • / etc / security / limit.conf

root soft nofile 240000

root hard nofile 320000

(рассматриваемый процесс запускается с правами root)

  • / etc / sysctl.conf

fs.file-max = 2000000

Оба установлены на ~ 200000.

Если проверить числооткройте описания файлов в системе, это всего лишь 996, даже если он выдает ошибки.

У меня одна и та же программа, запущенная на нескольких серверах Windows с большим количеством соединений, и у них никогда не было этой проблемы.

Любая идея, что может быть причиной этой ошибки?

Ответы [ 4 ]

6 голосов
/ 08 марта 2012

Причина, по которой ошибка не возникает в Windows, может быть связана с завершением сборки мусора.Если вы явно не закроете свои сокетные соединения, сокеты будут закрыты, когда они собраны.

Это несколько умозрительно, но если Mono не запускает сборку мусора, пока не увидит, что у вас заканчивается память, и он никогдане хватает сокетов памяти никогда не закрываются.Платформа Windows .NET может запускать сборщик мусора регулярно или когда он видит, что у вас заканчиваются файловые дескрипторы, что может объяснить разницу.

В качестве теста вы можете принудительно запустить сборку мусора вручную (GB.Collect) на регулярной основе.интервалы, и если это исправит ваши ошибки, правильным решением было бы не полагаться на сборку мусора для закрытия сокетов, обязательно закрывая их вручную в своем коде.Принудительная ручная сборка мусора приносит свои проблемы.

3 голосов
/ 20 февраля 2013

Сначала я столкнулся с подобной проблемой, но это то, что я сделал, чтобы она заработала:

sysctl -w net.inet.ip.portrange.first=3000  
sysctl -w net.inet.ip.portrange.hifirst=3000  
sysctl -w kern.maxfiles=900000  
sysctl -w kern.maxfilesperproc=900000  
ulimit -n 900000  

Я запустил процесс под пользователем root вместо обычного пользователя (другое мягкое ограничение) и смог создать до 100 000 подключений. Обратите внимание, что ulimit связан с оболочкой, поэтому необходимо вводить моно (yourapp.exe) в той же оболочке, что и ulimit, а не из MonoDevelop.

Для разработки под OSX 10.7.5.

0 голосов
/ 03 августа 2012

Вы пробовали установить ulimit как root?

На некоторых дистрибутивах может работать следующее:

Проверьте ulimit:

Command: sudo ulimit -n
Response: 1024

Set ulimit:

Command: sudo ulimit -n 65500

Reboot

Проверьте ulimit:

Command: sudo ulimit -n
Response: 65500

Мое собственное тестирование на «Ubuntu Precise» вернуло ошибку, сообщающую, что команда не найдена. Следующее, однако, сработало для меня http://posidev.com/blog/2009/06/04/set-ulimit-parameters-on-ubuntu/ (замените «user» реальным именем пользователя, когда подстановочный знак не работает для обычных пользователей)

0 голосов
/ 24 января 2012

В Linux-соединениям TCP назначается дескриптор файла, поэтому, вероятно, он показывает слишком много открытых дескрипторов файлов. Вы закрываете свои TCP-соединения после того, как с ними покончено? Пример кода, демонстрирующий проблему, поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...