Конфигурация пула php-fpm
Параметры php-fpm
Полный список директив: https://www.php.net/manual/en/install.fpm.configuration.php
[www] - имя пула, обязательный параметр
user и group - Имя и группа, от имени которых будут работать процессы
user = www-data
group = www-data
listen - Файл unix сокета или tcp/ip сокета для прослушивания запросов от веб-сервера
listen = 127.0.0.1:9000
listen.backlog - размер очереди одновременно ожидающих подключений к сокету listen.backlog = 100
Если значение большое, а PHP-FPM не успевает обрабатывать все запросы, то веб-сервер дождется тайм-аута и отключится, выкинув 504 ошибку (Gateway Timeout, Шлюз не отвечает). Если значение маленькое, то клиентские запросы вообще не могут попасть в очередь и веб-сервер сразу выдает 502 ошибку (Bad Gateway, Неправильный шлюз)
listen.owner, listen.group, listen.mode - разрешения для unix-сокета, если он используется. В Linux необходимо установить доступ на чтение и запись, чтобы разрешить подключение с веб-сервера
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
listen.allowed_clients - Список ip-адресов, которым разрешено подключение. Адреса разделяются запятыми. Имеет смысл только с tcp/ip сокетом
listen.allowed_clients = 127.0.0.1
pm.status_path - URI страницы статуса службы PHP-FPM
pm.status_path = /php-fpm-status
pm.status_listen - Значением может быть unix сокет или tcp/ip сокет, по которому будет приниматься запрос состояния. Создаёт новый невидимый пул, который может независимо обрабатывать запросы. Полезно, если основной пул занят долго выполняющимися запросами, так как всё ещё можно получить страницу состояния PHP-FPM до завершения долго выполняющихся запросов. Значение по умолчанию — как у директивы listen.
pm.status_listen = 127.0.0.1:9001
ping.path - URI страницы мониторинга службы PHP-FPM. Если значение не установлено, ping-страница отображаться не будет. Можно использовать для тестирования извне, чтобы убедиться, что служба PHP-FPM работает и отвечает.
ping.path = /php-fpm-ping
ping.response - Директива предназначена для настройки ответа на ping-запрос. Ответ формируется как text/plain со кодом ответа 200. Значение по умолчанию — pong.
ping.response = pong
access.log - Путь к файлу лога доступа. Префикс по умолчанию для относительного пути — /usr. Значение по умолчанию — не установлено
access.log = /var/log/$pool.php-fpm.access.log
slowlog - Путь к файлу лога медленных запросов
slowlog = /var/log/$pool.php-fpm.slow.log
request_slowlog_timeout - Время ожидания в секундах на обработку одного запроса, после чего PHP backtrace будет сохранён в файл slowlog
request_slowlog_trace_depth - Глубина трассировки стека вызовов для журнала slowlog
request_terminate_timeout - ремя ожидания в секундах на обработку одного запроса, после чего рабочий процесс будет принудительно завершён. Этот вариант следует использовать, когда опция max_execution_time в файле php.ini не останавливает выполнение скрипта по каким-то причинам
catch_workers_output - Перенаправляет stdout и stderr дочерних процессов в основной журнал ошибок. Если задано значение no — stdout/stderr будут перенаправлены в /dev/null. Значение по умолчанию — no.
catch_workers_output = yes
decorate_workers_output - Дополняет информацию от дочерних процессов для записи в основной журнал ошиблк. Имеет смысл только если catch_workers_output=yes
decorate_workers_output = yes
emergency_restart_threshold - Если кол-во дочерних процессов, которые завершились по сигналам SIGSEGV или SIGBUS, превышает указанное значение, то служба PHP-FPM будет перезапущена. Значение по умолчанию 0 (выкл)
emergency_restart_interval - Интервал времени в секундах, в течение которого должны завершиться дочерние процессы по сигналам SIGSEGV или SIGBUS, чтобы служба PHP-FPM была перезапущена. По умолчанию 0 (выкл)
process_control_timeout - задает интервал времени в секундах, в течение которого master-ппоцесс будет ждать корректного завершения рабочего процесса, прежде чем принудительно завершить его. Значение по умолчанию — 0 (без ограничений)
process.max - Максимальное кол-во дочерних процессов, которое может запустить служба PHP-FPM. Это нужно для контроля глобального количества процессов при использовании dynamic в большом количестве пулов, по умолчанию значение 0 (без ограничений)
process.priority - Указывает приоритет (nice) мастер-процесса ( по умолчанию не установлен )
daemonize - запустить PHP-FPM в фоновом режиме. Чтобы запустить PHP-FPM для отладки — нужно установить значение no. По умолчанию — yes
systemd_interval - Если PHP-FPM собран с интеграцией с Systemd, указывает интервал в секундах между оповещениями Systemd о своём состоянии
include=/etc/php/8.1/fpm/pool.d/*.conf - Подключить все файлы конфигурации пулов процессов из директории pool.d
Настройки производительности php-fpm
Параметр pm в PHP позволяет настроить, как менеджер процессов будет контролировать создание дочерних процессов
pm = dynamic — количество дочерних процессов настраивается динамически на основе директив: pm.max_children, pm.start_servers,pm.min_spare_servers, pm.max_spare_servers
PHP-FPM динамически регулирует количество доступных дочерних процессов и гарантирует постоянную доступность хотя бы одного из них
Режим dynamic задействует 5 параметров: pm.max_children, pm.start_servers, pm.min_spare_servers, pm.min_spare_servers, pm.max_spare_servers, pm.process_idle_timeout
При использовании pm.dynamic важную роль играют параметр min_spare_servers, так и параметр max_spare_servers, веб-трафик сильно меняется и у него есть высокие пики и глубокие спады
В режиме dynamic можно в итоге получить конфигурацию, которая по сути копирует static
Такой режим больше всего подходит, когда нужна экономия ресурсов (за счет уменьшения дочерних процессов при простое), но при этом бывают пиковые всплески, которые необходимо обработать.
pm = ondemand — процессы создаются по требованию (в отличие от динамического создания, когда pm.start_servers запускаются при запуске сервиса)
ondemand заставляет PHP-FPM форкать процессы при получении запросов
Режим ondemand завершает бездействующие процессы до нуля, когда трафика мало или нет вообще
Данный режим использует параметры: max_children, process_idle_timeout, max_requests
Возможно следует использовать именно этот режим при нехватке оперативной памяти
Режим ondemand чаще всего выбирают для сайта с низким трафиком, поскольку дочерние процессы будут создаваться только по необходимости, и завершаться, когда они больше не нужны
С одной стороны — не будет запущено лишних процессов, с другой стороны — клиентам придётся подождать запуска процесса
pm = static — количество дочерних процессов фиксировано и указывается параметром pm.max_children
Static гарантирует, что обработка пользовательских запросов всегда доступна фиксированному количеству дочерних процессов
В данном режиме часть процессов будут бездействовать, даже при небольшой активности пользователей. Простаивающие процессы ждет пиков трафика и реагирует моментально.
Не нужно ждать пока pm создаст дочерние процессы, а потом завершит их, когда истечет период pm.process_idle_timeout
Режим static следует выбирать для сайта с высоким трафиком, где требуется как можно меньшее время ответа, когда есть постоянная высокая нагрузка и большой объём памяти
Параметр PHP-FPM pm static во многом зависит от свободной памяти на сервере. Если памяти мало, лучше выбрать ondemand или dynamic
pm.max_children - число дочерних процессов, которые будут созданы, когда pm установлен в static или максимальное число процессов, которые будут созданы, когда pm установлен в dynamic. Устанавливает ограничение на число одновременных запросов, которые будут обслуживаться
Значение pm.max_children следует устанавливать таким образом чтобы перегрузить процессоры и накопить кучу операций PHP-FPM, ожидающих выполнения. Память и процессор будут работать без чрезмерной перегрузки
Если значение слишком маленькое, при возрастании нагрузки лимит исчерпается и сайт начнёт тупить. Если значение слишком большое, исчерпается оперативная память
pm.max_spare_servers - определяет максимальное количество процессов в состоянии ожидания
Если нет нагрузки на приложение, PHP-FPM удалит лишние процессы с целью сохранить оперативную память.
Значение примерно будет соответствовать значению pm.start_servers. Рекомендуется установить значение примерно 75% от pm.max_children
pm.start_servers помогает гарантировать постоянную доступность хотя бы одного из дочерних процессов, что важно в режиме dynamic, когда нужна экономия ресурсов, но при этом бывают пиковые всплески, которые необходимо обработать
pm.start_servers - используется, только когда pm установлен в dynamic. Значение по умолчанию рассчитывается по формуле min_spare_servers + (max_spare_servers - min_spare_servers) / 2
Значение будет равно - количество ядер процессора х 4. Рекомендуется установить значение pm.start_servers примерно 50% от pm.max_children.
pm.min_spare_servers — минимальное количество процессов в режиме ожидания (ничего не обрабатывающих) в настройках сервиса PHP-FPM. Если количество процессов меньше, будет создан ещё один. Данный запас нужен, чтобы PHP-FPM смог быстро обработать новые запросы, не тратя время на запуск новых процессов и должен быть меньше чем max_spare_servers
Значение будет равно: количество ядер процессора х 2
Рекомендуется установить значение в 25% от pm.max_children
Используется только для dynamic
max_requests - это максимальное количество запросов, которое обработает дочерний процесс, прежде чем будет уничтожен
pm.process_idle_timeout — это параметр конфигурации PHP-FPM, который указывает время простоя в секундах, по истечении которого дочерний процесс будет убит. Эта настройка помогает освободить ресурсы, когда они не активно обслуживают запросы
Лучший способ определить max_children — выяснить, сколько памяти использует каждый дочерний процесс, затем разделить максимально доступный объём оперативной памяти, на память одного процесса
Узнать сколько памяти в среднем потребляет дочерний процесс php-fpm, можно с помощью команды:
sudo ps aux --sort=rss -u www-data | grep -e php-fpm -e RSS
Например размер оперативной памяти 50 ГБ, из который на php-fpm можно потратить только 30 Гб.
Cредний размер выделяемой памяти на один процесс составляет 150 Мб
Тогда max_children будет примерно равен 200 процессов
pm = dynamic
max_children = 200
pm.max_spare_servers = 150
pm.start_servers = 75
pm.min_spare_servers = 40
max_requests = 500
Данный расчет примерный, и зависит от пиковой нагрузки на сервер, возможно правильно будет оставить определенный запас дочерних процессов на случай резкого увеличения трафика
Рекомендуется постепенно настраивать параметры, тестируя и корректируя значения на каждом шаге в разные периоды времени работы веб-сервера
Приложение можно разделить на несколько частей с использованием разных пулов
Например для обслуживания фронтенда и бекэнда, можно использовать разные пулы. Оба будут иметь одного и того же пользователя и группу, но иметь разные конфигурации менеджера процессов и подключены через разные сокеты.
Настройки php-fpm:
#/etc/php/8.1/fpm/pool.d/www.conf
; frontend [frontend] listen = /var/run/php-fpm-frontend.sock user = www-data group = www-data listen.owner = www-data listen.group = www-data pm = static pm.max_children = 5
; backend [backend] listen = /var/run/php-fpm-backend.sock user = www-data group = www-data listen.owner = www-data listen.group = www-data pm = ondemand pm.max_children = 5 pm.process_idle_timeout = 10s
Настройки nginx:
server { listen 80; server_name test-site.localdomain; root /var/www/test-site/public;
access_log /var/log/nginx/test-site.access.log; error_log /var/log/nginx/test-site.error.log error; index index.php;
set $fpm_socket "unix:/var/run/php-fpm-frontend.sock";
if ($uri ~* "^/api/") { set $fpm_socket "unix:/var/run/php-fpm-backend.sock"; }
location / { try_files $uri $uri/ /index.php;
location ~ .php$ { fastcgi_split_path_info ^(.+.php)(/.+)$; fastcgi_pass $fpm_socket; fastcgi_index index.php; include fastcgi.conf; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } } }
Это создаст конфигурацию виртуального хоста, которая отправляет запросы в пул фронтенда или бэкенда в зависимости от запрошенной локации
RSS (Resident Set Size) — это резидентная память, которая показывает, сколько физической памяти занято процессом в момент вывода команды. Она не включает память, которая заменяется. RSS содержит динамические библиотеки, с которыми связан процесс и которые загружены в физическую память. Также в неё входит память стека и кучи
VSZ (Virtual Memory Size) — это виртуальная память. Она содержит всю память, к которой может получить доступ процесс, включая память, которая заменяется, память, которая выделена, но ещё не используется, и память из разделяемых библиотек
RSS показывает, сколько памяти используется процессом, VSZ — всю память, к которой процесс может получить доступ
#Просмотреть все процессы php-fpm из вывода команды top
top -bn1 | grep php-fpm
#Примерно тот же результат покажет команда ps
#В данном случае будут показаны процессы запущенные от пользователя www-data
#Процессы будут отсортированы по объему резидентной памяти RSS
ps aux --sort=rss -u www-data | grep -e php-fpm -e RSS | wc -l
#Чтобы проверить результат внесенных изменений запустите
#Из вывода можно будет увидеть, что доступно ... процессов
pstree -c -H -S
Каждый дочерний процесс способен обрабатывать, к примеру, один запрос к приложению за раз
Если для параметра max_children установлено значение 5, а запросов 10, скорее всего, в логах появится что-то вроде этого:
WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
Это приведёт к тому, что некоторые запросы будут отложены пока не освободится достаточное количество дочерних процессов
Самый простой способ получить текущие значения настроек PHP-FPM без чтения файла конфигурации — использовать эту команду:
#Вывод настроек для каждого пула
php-fpm82 -tt
[09-Jan-2025 14:33:12] NOTICE: [www]
[09-Jan-2025 14:33:12] NOTICE: prefix = undefined
[09-Jan-2025 14:33:12] NOTICE: user = www-data
[09-Jan-2025 14:33:12] NOTICE: group = www-data
[09-Jan-2025 14:33:12] NOTICE: listen = /var/run/php-fastcgi.sock
[09-Jan-2025 14:33:12] NOTICE: listen.backlog = -1
[09-Jan-2025 14:33:12] NOTICE: listen.acl_users = undefined
[09-Jan-2025 14:33:12] NOTICE: listen.acl_groups = undefined
[09-Jan-2025 14:33:12] NOTICE: listen.owner = www-data
[09-Jan-2025 14:33:12] NOTICE: listen.group = www-data
[09-Jan-2025 14:33:12] NOTICE: listen.mode = 0660
[09-Jan-2025 14:33:12] NOTICE: listen.allowed_clients = 127.0.0.1
[09-Jan-2025 14:33:12] NOTICE: process.priority = undefined
[09-Jan-2025 14:33:12] NOTICE: process.dumpable = no
[09-Jan-2025 14:33:12] NOTICE: pm = static
[09-Jan-2025 14:33:12] NOTICE: pm.max_children = 100
[09-Jan-2025 14:33:12] NOTICE: pm.start_servers = 5
[09-Jan-2025 14:33:12] NOTICE: pm.min_spare_servers = 5
[09-Jan-2025 14:33:12] NOTICE: pm.max_spare_servers = 17
[09-Jan-2025 14:33:12] NOTICE: pm.max_spawn_rate = 32
[09-Jan-2025 14:33:12] NOTICE: pm.process_idle_timeout = 10
[09-Jan-2025 14:33:12] NOTICE: pm.max_requests = 100
[09-Jan-2025 14:33:12] NOTICE: pm.status_path = /status-www
[09-Jan-2025 14:33:12] NOTICE: pm.status_listen = undefined
[09-Jan-2025 14:33:12] NOTICE: ping.path = undefined
[09-Jan-2025 14:33:12] NOTICE: ping.response = undefined
[09-Jan-2025 14:33:12] NOTICE: access.log = undefined
[09-Jan-2025 14:33:12] NOTICE: access.format = undefined
[09-Jan-2025 14:33:12] NOTICE: slowlog = /var/log/php-fpm.log.slow
[09-Jan-2025 14:33:12] NOTICE: request_slowlog_timeout = 0s
[09-Jan-2025 14:33:12] NOTICE: request_slowlog_trace_depth = 20
[09-Jan-2025 14:33:12] NOTICE: request_terminate_timeout = 0s
[09-Jan-2025 14:33:12] NOTICE: request_terminate_timeout_track_finished = no
[09-Jan-2025 14:33:12] NOTICE: rlimit_files = 0
[09-Jan-2025 14:33:12] NOTICE: rlimit_core = 0
[09-Jan-2025 14:33:12] NOTICE: chroot = undefined
[09-Jan-2025 14:33:12] NOTICE: chdir = /
[09-Jan-2025 14:33:12] NOTICE: catch_workers_output = no
[09-Jan-2025 14:33:12] NOTICE: decorate_workers_output = yes
[09-Jan-2025 14:33:12] NOTICE: clear_env = yes
[09-Jan-2025 14:33:12] NOTICE: security.limit_extensions = .php .phar
[09-Jan-2025 14:33:12] NOTICE:
[09-Jan-2025 14:33:12] NOTICE: configuration file /etc/php82/php-fpm.conf test is successful
Если было порождено слишком много дочерних процессов, все они используются, и на сервере для них просто не хватает памяти. Если после перезапуска PHP-FPM использование памяти падает, а затем постепенно возрастает до предела, это свидетельствует об утечке памяти в коде приложения, иначе говоря после отработки скриптов, память у процессов не освобождается
Если дочерних процессов слишком много, на сервере для них может не хватать памяти.
Несколько процессов могут и обычно будут совместно использовать часть памяти, поэтому трудно точно определить реальное использование памяти одним процессом
Чтобы вычислить общий объем памяти, используемый программой, можно использовать скрипт python
wget https://raw.githubusercontent.com/pixelb/ps_mem/master/ps_mem.py
chmod a+x ps_mem.py
sudo python3 ps_mem.py
Private + Shared = RAM used Program
2.4 MiB + 2.5 MiB = 5.0 MiB sshd (7)
5.5 MiB + 3.6 MiB = 9.2 MiB nginx (4)
21.6 MiB + 57.5 KiB = 21.7 MiB memcached
25.9 MiB + 3.5 KiB = 25.9 MiB telegram
28.6 MiB + 27.5 KiB = 28.6 MiB bundle
34.8 MiB + 2.0 MiB = 36.8 MiB beam.smp
19.1 MiB + 32.6 MiB = 51.7 MiB postgres (9)
1.7 GiB + 78.7 MiB = 1.8 GiB php-fpm82 (108)
---------------------------------
2.0 GiB
=================================
Строка:
1.7 GiB + 78.7 MiB = 1.8 GiB php-fpm82 (108)
означает, что 108 процессов PHP-FPM используют 1.8 ГБ памяти. Один процесс использует около 16 МБ
Другая полезная команда позволяет определить определить количество незадействованных и активных процессов используя значение pm.status_path
# curl localhost/status-www
pool: www
process manager: static
start time: 08/Jan/2025:20:05:08 +0300
start since: 66660
accepted conn: 796
listen queue: 0
max listen queue: 0
listen queue len: 0
idle processes: 99
active processes: 1
total processes: 100
max active processes: 34
max children reached: 0
slow requests: 0
listen queue: - Количество запросов (backlog), ожидающих свободного процесса
max listen queue - Максимальное количество запросов в очереди на прослушивание в любой момент времени
listen queue len - Максимально допустимый размер очереди прослушивания
idle processes Количество процессов, которые в настоящее время простаивают (ожидают запросов)
active processes Количество процессов, которые в настоящее время обрабатывают запросы
total processes Текущее общее количество процессов
max active processes Максимальное количество одновременно активных процессов
max children reached Было ли достигнуто максимальное количество процессов? Если да, то отображаемое значение будет больше или равно 1, иначе значение будет равно 0
slow requests Общее количество запросов, которые достигли настроенного request_slowlog_timeout
memory peak Пиковое значение объёма памяти, которую PHP выделил с момента запуска FPM-менеджера процессов
99 бездействующих процессов
Если происходит утечка памяти, память для одного процесса может заполниться до значения memory_limit, определённого в файле php.ini, по умолчанию это 128 MB. Для подстраховки можно использовать это значение как среднее для одного процесса PHP-FPM
Источник: https://www.dev-notes.ru/articles/devops/a-deeper-dive-into-optimal-php-fpm-settings/
Подробная статистика
Если нужна подробная статистика по состоянию процесса php-fpm, можно передать аргумент ?full
# curl localhost/status-www?full
pool: www
process manager: dynamic
start time: 09/Jan/2025:20:19:43 +0300
start since: 41742
accepted conn: 741
listen queue: 0
max listen queue: 0
listen queue len: 0
idle processes: 13
active processes: 1
total processes: 14
max active processes: 6
max children reached: 0
slow requests: 0
************************
pid: 24584
state: Idle
start time: 09/Jan/2025:20:19:43 +0300
start since: 41742
requests: 54
request duration: 322756
request method: -
request URI: -
content length: 0
user: -
script: -
last request cpu: 86.75
last request memory: 41943040
************************
pid Системный PID-идентификатор процесса
state Состояние процесса — Idle, Running
start time Дата и время начала процесса
start since Количество секунд с момента начала процесса
requests Общее количество обслуженных запросов
request duration Общее время в микросекундах, затраченное на обслуживание последнего запроса
request method Метод HTTP последнего обслуженного запроса
request uri URI-идентификатор последнего обслуженного запроса (после обработки веб-сервером он всегда может быть равен /index.php, если вы используете шаблонный редирект фронт-контроллера)
content length Длина тела запроса, в байтах, последнего запроса
user HTTP-пользователь (PHP_AUTH_USER) последнего запроса
script Полный путь к скрипту, который выполнил последний запрос. Это будет '-', если не применимо (например, запросы страницы состояния)
last request cpu Процент занятого центральным процессором времени при выполнении последнего запроса. Это значение будет равно 0, если процесс не в состоянии Idle, потому что вычисление проводится после окончания обработки запроса. Значение может превысить 100 %, потому что метрика покажет, какой процент от общего времени работы процессора занял последний запрос, — в расчёте менеджер учтёт процессы на каждом ядре, тогда как 100 % — это значение только для одного ядра
last request memory Максимальный объем памяти, который потребил последний запрос. Это значение будет равно 0, если процесс не простаивает, поскольку вычисление проводится после окончания обработки запроса
Источник: https://www.php.net/manual/ru/fpm.status.php
Особенности использования режима Dynamic
Предположим, что в конфигурации пула используются следующие значения:
pm = dynamic
pm.max_children = 70
pm.start_servers = 20
pm.min_spare_servers = 20
pm.max_spare_servers = 40
В данном случае при запуске порождается 20 дочерних процессов, которые занимают память обычно используемую 20-ю процессами
Если к приложению поступают запросы, некоторые или все эти процессы будут активны и обрабатывать запросы
Если запросов не будет, тогда 20 этих процессов не будут завершены и будут по прежнему потреблять память
Устанавливать min_spare_servers меньшее, чем start_servers (например, 15), не имеет смысла, поскольку 20 дочерних процессов будут порождены немедленно, и даже если они будут простаивать, главный процесс не завершит 5 дочерних процессов, чтобы достичь этого минимума в 15. И не стоит задавать значение min_spare_servers больше, чем start_servers, поэтому лучшим вариантом, будет установка min_spare_servers равным значению start_servers
Теперь, если поступает много запросов и 20 дочерних процессов не хватает для их обработки, главный процесс породит дополнительные дочерние процессы до значения max_children, т.е. до 70
Через некоторое время ситуация нормализуется, и 70 процессов больше не нужны; большинство или все из них простаивают. В этом случае главный процесс завершит простаивающие дочерние процессы до значения max_spare_servers, в данном случае 40
В итоге останется 40 простаивающих процессов, которые не будут завершены в дальнейшем и будут использовать память, которую использует 40 дочерних процессов
Если нет необходимости получить 40 дочерних процессов, работающих в фоновом режиме, стоит уменьшить это значение или даже оставить его таким же, как start_servers
После перезапуска снова будут порождены 20 дочерних процессов на основе start_servers
Существует другая теория исходя из которой кол-во дочерних высчитывается по формулам:
pm.start_servers = number of CPU cores x 4
pm.min_spare_servers = number of CPU cores x 2
pm.max_spare_servers = number of CPU cores x 4
В данном следует учитывать не только ко-во ядер, однако в любом случае необходимо учитывать доступный размер оперативной памяти, размер выделенной памяти для одного процесса и др.
Будет правильно, постепенно отслеживать и настраивать параметры пула учитывая изменение нагрузки на сервер
Стоит обратить внимание еще на одну опцию pm.max_requests. Если есть утечка памяти, эта настройка может быть полезна для перезагрузки дочерних процессов после определённого количества запросов. Например, если установить значение 500, то после обработки 500 запросов дочерний процесс будет завершён (освободив таким образом всю накопленную память), а затем создан заново.
Тестирование веб-сервера
ApacheBench (ab) — однопоточная программа для командной строки, использующаяся для измерения производительности HTTP веб-серверов
Дополнительные настройки
С помощью опции slowlog можно отследить меделенные запросы
Для активации необходимо добавить в настройки пула строку:
slowlog = /var/log/php8.2-fpm.log.slow
request_slowlog_timeout - запросы, занимающие, например, 3 секунды и более
request_slowlog_trace_depth - это глубина трассировки стека вызовов для журнала slowlog. Значение по умолчанию — 20. Опция может быть полезна в том случае если необходимо узнать какой скрипт вызывается
Другие настройки на которые следует обратить внимание хранятся в файле: /etc/php/8.2/fpm/php-fpm.conf
#Первые две настройка говорят, что если 10 дочерних процессов не работают в течение одной минуты,
#то PHP-FPM должен перезапуститься автоматически
emergency_restart_threshold = 10
emergency_restart_interval = 1m
#Дочерний процесс будет ждать 10 секунд, прежде чем действовать по сигналу, отправленному от главного процесса
process_control_timeout = 10s
error_log - Путь к файлу журнала ошибок
log_level - Уровень журналирования ошибок (alert, error, warning, notice, debug)
Источник1: https://www.dev-notes.ru/articles/devops/a-deeper-dive-into-optimal-php-fpm-settings/
Источник2: https://www.php.net/manual/ru/install.fpm.configuration.php
PHP настройки в файле nginx.conf
Поскольку эти настройки передаются в php-fpm как FastCGI-заголовки, php-fpm не привязывают к адресу, который доступен из внешнего мира, иначе кто угодно изменит настройки PHP
set $php_value "pcre.backtrack_limit=424242";
set $php_value "$php_value \n pcre.recursion_limit=99999";
fastcgi_param PHP_VALUE $php_value;
fastcgi_param PHP_ADMIN_VALUE "open_basedir=/var/www/htdocs";
Примечание
Пулы — не механизм безопасности, поскольку не обеспечивают полного разделения; например пулы будут использовать один экземпляр OPcache
php.ini
#Время выполнения скрипта
max_execution_time = 30
#Объем памяти выделенный скрипту
memory_limit = -1
#задаёт максимальное время в секундах,
#в течение которого скрипт должен разобрать все входные данные,
#переданные запросами вроде POST или GET
max_input_time = 60
#Лимит на объем загружаемого файла
post_max_size = 8M
upload_max_filesize = 2M
#максимальное время ожидания (в секундах) для выполнения сетевых операций
default_socket_timeout = 60
#pgsql.
Примеры ошибок в логах PHP
server reached pm.max_children setting (100), consider raising it
Если кол-во дочерних процессов php-fpm больше максимально-допустимого кол-ва дочерних процессов ( pm.max_children, pm.start_servers,pm.min_spare_servers, pm.max_spare_servers ), тогда в логах php можно увидеть ошибки:
[27-Dec-2024 10:05:48] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 0 idle, an
d 98 total children
[27-Dec-2024 10:05:49] WARNING: [pool www] server reached pm.max_children setting (100), consider raising it
В логах nginx, который отправляет запросы к вышестоящему серверу php, возможно будет ошибки:
upstream timed out (110: Operation timed out) while reading response header from upstream, client: 192.168.***.***, server: *************.ru, request: "GET **********:197 HTTP/2.0", upstream: "fastcgi://unix:/var/run/php-fastcgi.sock", host:
В таком случае пользовательский веб-интерфейс будет тормозить или вовсе недоступен с ошибкой 504 в браузере
Возможные причины и способы решения данной проблемы в Nginx описанны ниже ( Часто встречаемые ошибки в логах NGINX )
Если изменение конфигурации php не устраняет проблемы, возможно, у вас просто недостаточно потоков/ядер процессора для обслуживания рабочих нагрузок PHP-FPM.
Источники
Связанные темы
Оптимизация запросов в Postgresql
Использование модуля pg_stat_statements в postgresql
Анализ производительности виртуальной машины