Недавно я перенес клиент на экземпляр EC2 с Nginx + PHP-FPM. Когда я впервые настраивал сервер, я установил pm=static
с 40 рабочими процессами. Примерно через неделю я решил поэкспериментировать с pm=dynamic
максимум 200 и минимум 30 рабочих.
Я заметил, что при статической настройке 40 процессов занимали около 2,3 ГБ памяти, тогда как при динамической настройке я наблюдал всплески 60 процессов, использующих только 1,2 ГБ памяти.
См. Диаграмму ниже из New Relic, мои аннотации выделены красным.
Вы можете видеть, что в течение дня 25 ноября я перешел со статического на динамический и перезапустил php-fpm. После этого мы видим, что 48 процессов занимают всего 990 МБ, а 60 процессов занимают всего 1,2 ГБ памяти.
Что может способствовать этому несоответствию между статическим и динамическим управлением? Может быть, с динамическим я установил максимальное количество запросов на 50? Возможно, использование статической памяти было связано скорее с утечкой памяти, чем с чем-то внутренним с php-fpm?
pm.max_requests
не является специфическим для какого-либо диспетчера процессов (pm
) Режим. Его преимущества заключаются в том, что рабочие процессы возрождаются после определенного количества запросов, которые они обрабатывают индивидуально.
Это могло бы избежать утечек памяти в крайних случаях, но обычно это просто освобождает выделенную память, накопленную при выполнении скриптов, требующих большого количества памяти. Выделения памяти накапливаются, и общий объем выделенной памяти растет, но освобождается только при выходе (то есть при возрождении).
Как вы выразились, похоже, вы не активировали pm.max_requests
когда используешь pm static
. Вы должны были увидеть разницу, и определенно больше, чем ровную линию.
pm dynamic
имеет дополнительное преимущество остановки рабочих в зависимости от количества незанятых процессов среди них (pm.min_spare_servers
, pm.max_spare_servers
), которые являются своего рода метрикой, измеряющей мгновенную нагрузку. Остановка бесполезных процессов освобождает связанную выделенную память за счет обработки процессов (ЦП), что pm.min_spare_servers
противодействует обеспечению подушки безопасности в случае пиков, поддерживая простаивающих работников готовыми обрабатывать запросы.
Теперь, если вы действительно заботитесь о своей памяти, pm ondemand
является более агрессивным, (де) порождает процессы по мере (не) необходимости (больше). Этот режим ближе всего к краю, так как он не поглощает шипы так же хорошо, как pm dynamic
, но он потребляет меньше всего памяти (за счет использования большего количества ЦП для управления процессами).
TL; DR
Выделение памяти складывается для любого рабочего процесса. Если конкретный запрос требовал много памяти, он превысит выделение памяти обработчика, и оно не будет освобождено, пока процесс не остановится.
Использовать pm.max_requests
для повторного использования процессов, какой бы режим вы ни использовали.
pm.dynamic
перезапустит процессы по другому критерию, то есть по нагрузке, и завершит процессы, когда слишком большая их часть простаивает. Более высокая текучесть процессов с большей вероятностью предотвратит их чрезмерное потребление памяти за счет большего количества циклов процессора, используемых для управления процессами.