странная ситуация с .Net OutOfMemoryExceptions в IIS / Windows 2008 R2, выбрасываемых на случайные страницы поражаемого приложения.
У нас есть около 1000 отдельных сайтов, которые представляют собой одно и то же приложение .Net (разные папки кодовой базы и пулы приложений для каждого сайта). 64-битная Windows, работающая под управлением .Net 2.0, приложение компилируется с флагом AnyCPU.
Поскольку тот же самый код работает на старом сервере и никогда не вызывает исключений outofmemoryexceptions, мы не тратим много времени на профилирование приложения и изучение дампов, а также на оптимизацию кода, которая поможет избежать фрагментации кучи больших объектов (поэтому мы надеемся получить некоторые подсказки о возможных проблемах конфигурации сервера, которые могут быть причиной большего, чем просто посмотреть в кодовая база и ее оптимизация ...).
Конфигурация 1 - Rackspace CloudSites (виртуальный хостинг, к нему можно подключиться только по FTP, доступа к настройкам IIS нет):
1, мы не можем управлять им, но нам сказали, что каждый пул приложений имеет ограничение на повторное использование 250 МБ. Из наших 1000 сайтов многие сайты (20-50), по-видимому, используют один и тот же пул приложений. Мы никогда не получаем OutOfMemoryExceptions здесь, и приложение работает на нем годами.
Конфигурация 2 - выделенный сервер Rackspace (полный контроль):
Сервер-монстр с выделенной оперативной памятью 128 ГБ, каждый сайт имеет собственный пул приложений. Все пулы приложений имеют одинаковые настройки (ограничение на повторное использование 350 МБ). Не уверен, имеет ли это значение, но размер файла подкачки на этом сервере составляет 4 ГБ (не знаю, что такое Конфиг 1 - нужно ли это увеличивать / решать?).
Обе конфигурации имеют балансировку нагрузки между 2 или 3 веб-серверами, но это действительно не имеет значения как таковое, поскольку мы видим, что сайты с БЕЗ ТРАФИКА убиваются с помощью OutOfMemoryExceptions.
Пока я писал эту публикацию, этот пост набирал обороты, вот основные моменты
frequentHitThreshold
и frequentHitTimePeriod
значения (просмотрите счетчики производительности кэша веб-служб и внесите соответствующие изменения)Оригинальный ответ
Не уверен, имеет ли это значение, но размер файла подкачки на этом сервере составляет 4 ГБ (не знаю, что есть в Конфигурации 1 - нужно ли это увеличивать / решать?
Это здесь ^
прямо здесь ^
посмотри на это.
Готов поспорить, что это именно та причина, по которой ваши приложения выдают OutOfMemoryException
в ответ на, казалось бы, самые случайные и безобидные запросы, но чтобы понять почему, давайте проясним одну вещь:
OutOfMemory
не означает, что вашему серверу не хватает памяти!Я знаю, это звучит как плохая шутка, но на самом деле это не так. Не операционная система жалуется на истощение памяти - это процесс.
Если это последнее утверждение не имело для вас смысла, продолжайте читать.
Когда процесс выделяет память из ОС, он поступает в виде последовательности фрагментов, называемых страницы, 4 килобайта за кусок, который процесс может рассматривать как собственное (это обычно называется виртуальным адресным пространством).
Поскольку объект (например, строка, XML-документ, изображение или что-то еще, что вам нужно сохранить в памяти) может превышать размер страницы в 4 КБ, процессу потребуется время от времени выделять несколько последовательных страниц из этой памяти.
Однако со временем пространство памяти становится фрагментированным даже при использовании .NET CLR. Сборщик мусора попытается сделать все возможное, чтобы помочь вашему приложению лучше использовать адресное пространство, переупорядочивая страницы в рабочем наборе во время сборок (это практически то же самое, что и дефрагментация диска), но указатели на кучу больших объектов например, останется нетронутым.
Еще недавно объяснено в этом ответе, IIS также попытается сохранить как можно больше кэшируемых выходных объектов (таких как статические файлы размером до 256 КБ) в том же процессе, который обслуживает ваше приложение - в дополнение к предложению в этом ответе вы также можете попробовать настроить пороги частоты кэширования с использованием <serverRuntime>
элемент конфигурации.
В любом случае IIS 7.5 - в его конфигурации по умолчанию - глубоко заботится о выделении достаточного количества памяти для своих рабочих процессов, и даже при «БЕЗ ТРАФИКА» нередко можно увидеть, что рабочий процесс требует первые 100 МБ при запуске, даже если кодовая база приложения на диске немного меньше.
Чтобы увидеть, что 100 * 1000 процессов - это не так уж и далеко от 128 ГБ оперативной памяти, которую может предложить ОС, не требуется математика на уровне высшего образования. Несмотря на то, что IIS пытается выделить столько памяти для своих рабочих процессов, сколько необходимо, в какой-то момент он останавливается, чтобы оставить место для операционной системы на уровне около 85% от общего объема установленной памяти, независимо от того, сколько мегабайтов или гигабайт оперативной памяти может быть (это не факт, что я видел документацию, но взят из личного опыта с большим количеством установок IIS с различными характеристиками оборудования).
На этом этапе операционная система может помочь освободить память, выделяя вместо этого страницы из файла подкачки - страниц, хранящихся в файле на физическом диске. Поскольку дискового пространства часто достаточно, выделение больших фрагментов дискового хранилища - не такая уж сложная задача, но если требуется страничная подкачка памяти для 1000 процессов, и это разрешено только на 4 ГБ пространства, это не займет много времени. процессы не смогут выделять более длинные последовательности нефрагментированной памяти и затяжка!: процесс бросает OutOfMemoryException
, это просто означает, что ему не удалось найти достаточно соседних страниц для чего-либо в доступном виртуальном адресном пространстве.
Это даже не обязательно должны быть большие объекты. Они просто должны быть больше, чем максимальное количество смежных страниц, доступных во время выполнения. Теоретически вы можете получить исключение OutOfMemory при попытке добавить один символ в строку, размер которой в настоящее время превышает 2 КБ.
Ответ Microsoft на этот вопрос всегда был: «это зависит», но как минимум 1 x RAM + 257 МБ (это объем памяти, необходимый системе для записи полного дампа памяти).
Эмпирическое правило кажется примерно 1,5-2 x RAM, но опять же, это зависит, и был опубликован ряд статей о том, как определить правильный минимальный и максимальный размер файла подкачки в данной системе. Я включил самый подходящий вариант внизу.
Обязательно следите за диском, содержащим файл подкачки, если счетчики длины очереди диска начинают набирать обороты, вы можете переместить его на выделенный диск или распределить по нескольким дискам.
Как определить подходящий размер файла подкачки для 64-битных версий Windows
Вы можете отключить ограничения памяти пула приложений (установите для него значение 0), чтобы быстро позволить пулу приложений занять столько, сколько необходимо. Однако похоже, что что-то протекает и в конечном итоге займет всю доступную память (и снова перезапустит пул приложений).
Проверьте свои c:\windows\system32\LogFiles\HTTPERR
файл журнала сообщений о критических ошибках.
Вам не нужно изменять настройки файла подкачки, который используется только при исчерпании 128 ГБ ОЗУ.
Чтобы отследить источник утечки памяти, вам нужно будет покопаться в Trace Logs или DebugDiag (не самая простая задача):
Как использовать средство диагностики отладки IIS для устранения утечки памяти в процессе IIS
Устранение проблем с утечкой собственной памяти в пуле приложений IIS 7.x
Наша проблема была решена путем переключения пулов приложений 1000+ в 32-битный режим вместо 64-битного по умолчанию. Мы смогли подтвердить это, вернувшись к 64-битной версии и сразу увидев исключения из памяти.
Я считаю, что пункты Джессена в файле подкачки имеют вес. . . поскольку для увеличения файла подкачки потребовался перезапуск системы, мы попытались переключиться на пулы приложений в 32-битном режиме (который не требует перезапуска) и нам повезло.
Если у кого-то есть интересные комментарии по этому поводу, пожалуйста, не стесняйтесь!
Спасибо!