Примерно раз в неделю, но иногда даже пару раз в день после нескольких дней работы мои экземпляры 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-скрипта. Некоторый код, связанный с обработкой SSL-соединения, делает что-то не так - утечка исчезла, когда я переключился на HTTP. Список изменений в Curl ссылается на несколько утечек памяти SSL, которые были исправлены в 7.19.5 (мы были на 7.18.2), поэтому я попробую это позже.
Тем временем я работаю с очень низким MaxRequestsPerChild, который держит Apache в разумных пределах. Спасибо всем!