Примерно раз в неделю, но иногда даже пару раз в день после нескольких дней нормальной работы мои экземпляры EC2 перестают отвечать. Графики памяти Мунина рассказывают довольно простую историю: память, выделенная для «приложений», начинает расти и не останавливается до тех пор, пока не будет полностью использован своп и экземпляр фактически не будет поставлен на колени. Другой настраиваемый график показывает, что это постоянно растущий процесс apache2.
Я запускаю стандартную предварительную установку Apache с mod_php и несколькими скриптами PHP. Как вы можете видеть на графике ниже, происходит что-то, что запускает процессы apache2, которые начинают потреблять все больше и больше памяти. Первый зеленый всплеск, который я поймал вовремя и перезапустил Apache, прежде чем ситуация вышла из-под контроля. Второй спайк прошел немного дальше, и пришлось сразу перезагружать экземпляр.
Мне интересно, как это лучше всего отладить. За исключением настройки PHP с FastCGI и запуска его в собственных процессах, что является хорошим способом выяснить, является ли это Apache или комбинация PHP и моего кода, вызывающая чрезмерное использование памяти? Какие шаги вы, ребята, предпримете, чтобы отследить эту проблему?
ОБНОВЛЕНИЕ: я смог отследить утечку после вовлечения strace, как Мэтт предложил ниже.
Обнаружив процесс apache2, который постепенно и непрерывно увеличивался в памяти, я добавил еще несколько вызовов error_log () в свой PHP-скрипт, который распечатал общее количество RSS, использованного в различные моменты его выполнения (с использованием вывода ps). Однако это оказалось ложным - хотя оказалось, что RSS перескакивал только после того, как мой скрипт был завершен, более поздняя отладка показала, что на самом деле это не так. Быть осторожен!
К счастью, все эти вызовы error_log () в конце концов оказались полезными. Когда я зажег strace (strace -p <pid> -tt -o trace.log -s 256
), Я увидел, что для каждого запроса процесс выделял около 400 КБ памяти (найдите системный вызов brk и вычтите параметр первого вызова из параметров последнего вызова - некоторые обычно приходят один за другим). Затем я поискал самый последний системный вызов write, который содержал мое сообщение error_log (), в котором говорилось, в какой точке сценария выделяется память. С помощью еще нескольких стратегически размещенных вызовов error_log () для более точного определения местоположения я наконец нашел виновника.
Утечка памяти происходила, когда мы вызывали curl_exec () из нашего PHP-скрипта. Какой-то код curl, связанный с обработкой SSL-соединения, делает что-то не так - утечка исчезла, когда я переключился на HTTP. Журнал изменений Curl ссылается на несколько утечек памяти SSL, которые были исправлены в версии 7.19.5 (мы были в версии 7.18.2), так что я попробую это в следующий раз.
А пока я использую очень низкий MaxRequestsPerChild, что удерживает Apache в разумных пределах. Спасибо всем!
Отслеживание того, ЧТО вызывает проблему, может оказаться занозой в заднице. Первое, что я сделал бы, если бы у меня возникла такая проблема, - это уменьшить MaxRequestsPerChild
на агрессивно низкое число (~ 100-200) и посмотрите, имеет ли это значение. Если это так, то, вероятно, у вас есть код, в котором происходит утечка памяти в каком-то цикле, и вы захотите запустить аудит кода.
Еще одна вещь, на которую стоит обратить внимание, - это полный статус Apache, посмотрите, сможете ли вы узнать, какой конкретный запрос вызывает утечку памяти. Получите PID подозреваемых процессов и запустите их.
Пятница ровно в 23:00? Это соответствует времени резервного копирования? Имеется ли в вашей системе доступ к вводу-выводу для обслуживания процессов и резервного копирования в это время? У вас есть трендовое программное обеспечение, которое также отслеживает # процессы или даже табло Apache, как насчет дискового ввода-вывода?
В первый Я бы посчитал, сколько памяти занимает каждая процедура, а затем установил разумный предел для MaxRequests в apache, чтобы $ procmem * $ procs не превышал доступную память. Я подозреваю, что ваш экземпляр необходимо перезагрузить, потому что OOM начинает охоту на ведьм, которая, вероятно, (часто) не очень плодотворна. Вы необходимость чтобы ваша коробка могла справиться с этими тяжелыми временами, оставаясь в пределах своих границ и не переходя на свопинг и, конечно же, не OOM. Это сложнее, если у вас есть cronjobs, и чрезвычайно сложно, если указанные cronjobs запускаются в одностороннем порядке, не убедившись, что запуск безопасен (т.е. каждые 5 минут скрипт не может проверить, выполняются ли последние 5 минут).
Теперь, когда вы убедились, что даже если что-то пойдет не так, вам не придется перезагружать компьютер, все пойдет намного лучше. Вы сможете войти в систему в эти тяжелые времена и получить хорошее представление о том, что происходит, используя top, dstat, free -m, iostat и т. Д.
Метод Мэтта, возможно, стоит попробовать, но его следует использовать только в качестве инструмента для устранения неполадок. Я не рекомендую сохранять его таким образом, потому что он значительно усложнит поиск общей проблемы в следующий раз, когда вы ее будете искать. Тем не менее, это действительно только выявит проблемы с apache / модулями, а не что-либо в вашем коде. Думаю, вы согласитесь, что шансы велики, что это не какая-то утечка памяти в модуле apache (при условии, что вы используете надежный дистрибутив).
Первый вопрос, который следует задать: какое приложение работает через Apache?
Это написанное вами приложение или стороннее приложение?
На какие еще компоненты / пакеты он ссылается?
Вы в курсе своих пакетов?
Что-нибудь конкретное в вашем httpd.conf
файлы, связанные с производительностью?
Если ваша проблема вызвана приложением PHP, и если вы написали программное обеспечение самостоятельно, я рекомендую вам использовать профилировщик, например, Быстрый профилировщик PHP. Если у вас происходит много транзакций с базой данных, тогда программное обеспечение, например, Контрольная база может помочь вам найти там проблему.