Сайт использует сookies для хранения данных. Продолжая использовать сайт, вы даёте согласие на работу с этими файлами.

ОК
🌐
Клиент-сервер
Опубликовано:
19.10.2026
•
Обновлено:
19.10.2026

Nginx и PHP-FPM: настройка взаимодействия, параметры пула и диагностика ошибок 502 и 504

Данил Мануйлов

Связка веб-сервера Nginx и менеджера процессов PHP-FPM (FastCGI Process Manager) — стандартный стек для веб-приложений на базе PHP. В этой архитектуре Nginx принимает входящие сетевые соединения, обрабатывает TLS/SSL, отдает статический контент и проксирует динамические запросы. PHP-FPM отвечает за интерпретацию и исполнение программного кода в изолированных дочерних процессах (воркерах).

Нарушения в сетевом взаимодействии между сервисами, некорректные права доступа, ошибки в конфигурации пулов процессов или несогласованные таймауты приводят к сбоям в обслуживании пользователей. Чаще всего они выражаются в виде HTTP-ответов 502 Bad Gateway и 504 Gateway Time-out.


Как работает связка Nginx и PHP-FPM: жизненный цикл запроса

Nginx не имеет встроенного интерпретатора PHP. Вместо прямого исполнения скрипта веб-сервер работает в режиме обратного прокси (reverse proxy) и транслирует запросы через бинарный протокол FastCGI.

Цепочка обработки запроса строится следующим образом:

  1. Прием запроса: Клиент отправляет HTTP-запрос к Nginx.
  2. Маршрутизация: Nginx сопоставляет URI с блоками server и location. Если запрос соответствует правилу обработки PHP (например, location ~ \.php$), веб-сервер инициирует FastCGI-сессию.
  3. Формирование параметров: Nginx преобразует HTTP-заголовки и метаданные в переменные протокола FastCGI (SCRIPT_FILENAME, REQUEST_METHOD, QUERY_STRING и др.).
  4. Передача в сокет: Данные направляются по транспорту, указанному в директиве fastcgi_pass (Unix Domain Socket или TCP-порт).
  5. Обработка в пуле: Главный процесс PHP-FPM (master process) распределяет задачу свободному дочернему процессу (worker). Воркер выполняет PHP-скрипт, обращается к базе данных или сторонним API и генерирует тело ответа.
  6. Возврат данных: PHP-FPM передает статус, HTTP-заголовки и тело ответа обратно веб-серверу.
  7. Ответ клиенту: Nginx отправляет сформированный HTTP-ответ пользователю.
[Клиент]
   │ HTTP / HTTPS
   ▼
[Nginx]
   │ FastCGI (fastcgi_pass)
   │ ├── Unix Domain Socket (/run/php/php-fpm.sock)
   │ └── TCP Socket (127.0.0.1:9000)
   ▼
[PHP-FPM Master Process]
   │
   ├── [Worker 1] -> Выполнение скрипта (index.php)
   ├── [Worker 2] -> Свободен
   └── [Worker N] -> Свободен

Роль FastCGI и передача параметров

Протокол FastCGI поддерживает постоянный пул процессов для обработки запросов, исключая накладные расходы на запуск нового интерпретатора при каждом обращении.

Чтобы PHP-FPM корректно определил файл для исполнения на диске, Nginx передает системные переменные. Критически важной является директива fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;. Без нее менеджер процессов не сможет найти целевой файл и вернет ошибку Primary script unknown с кодом 404 или статус 502.

Unix Domain Socket против TCP Socket: что и когда выбирать

Для обмена данными между Nginx и PHP-FPM применяются два типа сетевых транспортов:

  • Unix Domain Socket (UDS): Специальный файл сокета в файловой системе (например, unix:/run/php/php8.2-fpm.sock).
    • Преимущества: Работает напрямую через оперативную память и ядро Linux без сетевого стека, обеспечивает минимальные задержки (latency) и не расходует TCP-порты.
    • Ограничения: Доступен только в пределах одной операционной системы (одного хоста или общего volume в контейнерах). Требует корректной настройки прав доступа на уровне файлов.
  • TCP Socket: Сетевое соединение по протоколу TCP/IP (например, 127.0.0.1:9000 или удаленный сетевой адрес).
    • Преимущества: Позволяет разносить веб-сервер и обработчики PHP по разным серверам или виртуальным машинам.
    • Ограничения: Создает дополнительные накладные расходы на упаковку сетевых пакетов и при высокой нагрузке может исчерпать доступные локальные порты (TIME_WAIT).

Рекомендация: Если Nginx и PHP-FPM находятся на одном хосте, предпочтительно использовать Unix Domain Socket. Если веб-сервер распределяет нагрузку на отдельный кластер серверов приложений — используется TCP Socket.


Базовая настройка Nginx и пула PHP-FPM

Для стабильной работы связки параметры виртуального хоста Nginx должны быть согласованы с конфигурацией пула PHP-FPM.

Конфигурация Nginx: блок location ~ \.php$

Пример настройки виртуального хоста Nginx с передачей запросов через Unix-сокет:

server {
    listen 80;
    server_name example.test;
    root /var/www/app/public;
    index index.php index.html;

    access_log /var/log/nginx/app_access.log;
    error_log /var/log/nginx/app_error.log warn;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        # Защита от исполнения несуществующих файлов
        try_files $uri =404;

        # Базовые параметры FastCGI
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        
        # Точка подключения к PHP-FPM
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;

        # Буферизация и таймауты
        fastcgi_connect_timeout 5s;
        fastcgi_send_timeout 60s;
        fastcgi_read_timeout 60s;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
    }

    location ~ /\.ht {
        deny all;
    }
}

Конфигурация пула PHP-FPM: директивы listen, pm и права доступа

Конфигурация пула по умолчанию располагается в /etc/php/8.X/fpm/pool.d/www.conf (Debian/Ubuntu) или /etc/php-fpm.d/www.conf (RHEL/AlmaLinux/Rocky).

Пример пула с Unix-сокетом:

[www]
user = www-data
group = www-data

; Сетевой транспорт
listen = /run/php/php8.2-fpm.sock

; Права доступа к сокету для Nginx
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

; Режим управления процессами
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
pm.max_requests = 1000

; Таймауты и логирование
request_terminate_timeout = 60s
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/www-slow.log
pm.status_path = /fpm-status

При использовании TCP-сокета директива listen настраивается следующим образом:

listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1

Управление процессами и таймаутами: предотвращение деградации

PHP-FPM поддерживает три режима управления процессами (pm):

  1. static: Количество воркеров постоянно и фиксируется параметром pm.max_children. Обеспечивает максимальное быстродействие на выделенных серверах, так как система не тратит ресурсы на создание и завершение процессов.
  2. dynamic: Количество процессов изменяется в диапазоне от pm.min_spare_servers до pm.max_spare_servers в зависимости от нагрузки, не превышая pm.max_children. Подходит для большинства типовых проектов.
  3. ondemand: Процессы создаются только по мере поступления входящих запросов и завершаются при простое. Экономит оперативную память при нерегулярном трафике, но увеличивает время ответа при первом обращении.

Расчет и настройка pm.max_children

Параметр pm.max_children определяет максимальное количество одновременно работающих процессов PHP. Неверный расчет этого значения приводит к нехватке памяти и аварийной остановке служб механизмом ядра Linux Out-of-Memory (OOM) Killer.

Формула безопасного расчета pm.max_children:

max_children = (Доступная RAM для PHP) / (Средний объем памяти одного воркера)

Порядок расчета:

  1. Вычтите из общего объема RAM сервера память, зарезервированную под системные службы, Nginx, СУБД и кэш.
  2. Определите среднее потребление памяти одним процессом PHP под реальной нагрузкой:
    ps --no-headers -o rss -C php-fpm8.2 | awk '{sum+=$1; count++} END {if (count>0) print sum/count/1024 " MB"}'
    
  3. Разделите доступную память на средний размер процесса. Например, при доступных 4096 МБ RAM и среднем размере воркера 80 МБ: 4096 / 80 ≈51 Рекомендуемое значение: pm.max_children = 50.

Директива pm.max_requests (например, 500–1000) перезапускает воркер после обработки указанного количества запросов, устраняя последствия возможных утечек памяти в сторонних библиотеках.

Согласование таймаутов Nginx и PHP

Несогласованность лимитов времени приводит к разрывам соединений. Настройки должны выстраиваться по возрастающей цепочке:

База данных / внешние API (cURL timeout: 10s)
  └─► PHP max_execution_time (30s)
        └─► PHP-FPM request_terminate_timeout (35s)
              └─► Nginx fastcgi_read_timeout (40s)
  • max_execution_time (в php.ini): Ограничивает время исполнения скрипта движком PHP (по умолчанию учитывает только процессорное время).
  • request_terminate_timeout (в www.conf): Принудительно завершает воркер сигналом SIGKILL, если время выполнения превысило лимит. Должно быть немного выше max_execution_time.
  • fastcgi_read_timeout (в nginx.conf): Время ожидания ответа от FastCGI-сервера со стороны Nginx. Должно превышать request_terminate_timeout, чтобы PHP успел корректно зафиксировать ошибку до закрытия соединения прокси-сервером.

Диагностика и устранение ошибки 502 Bad Gateway

Код 502 Bad Gateway указывает на то, что Nginx не смог установить связь с PHP-FPM, сокет оказался недоступен или соединение было аварийно прервано со стороны upstream.

[Клиент] ─── HTTP GET ───► [Nginx] ─── FastCGI ───X (Связь оборвана / отказ) [PHP-FPM]
   ▲                               │
   └─────── HTTP 502 ──────────────┘

Причина 1: Служба PHP-FPM остановлена или сокет недоступен

Если процесс PHP-FPM не запущен или путь к сокету указан с ошибкой, Nginx фиксирует отказ в соединении.

Запись в /var/log/nginx/error.log:

[error] 1234#0: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 192.0.2.1, server: example.test, request: "GET / HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000"

или для Unix-сокета:

[error] 1234#0: *1 connect() to unix:/run/php/php8.2-fpm.sock failed (2: No such file or directory) while connecting to upstream...

Решение:

  1. Проверьте статус службы:
    systemctl status php8.2-fpm
    
  2. Проверьте синтаксис конфигурации и запустите службу:
    php-fpm8.2 -t
    systemctl start php8.2-fpm
    
  3. Сверьте значение fastcgi_pass в Nginx и директиву listen в www.conf.

Причина 2: Неверные права доступа к Unix-сокету

Файл сокета существует, но пользователь рабочего процесса Nginx не имеет прав на чтение и запись.

Запись в /var/log/nginx/error.log:

[error] 1234#0: *1 connect() to unix:/run/php/php8.2-fpm.sock failed (13: Permission denied) while connecting to upstream...

Решение:

  1. Проверьте владельца и права на файл сокета:
    ls -la /run/php/php8.2-fpm.sock
    
  2. В файле www.conf задайте корректные параметры для пользователя веб-сервера:
    listen.owner = www-data
    listen.group = www-data
    listen.mode = 0660
    
  3. Перезапустите службу PHP-FPM:
    systemctl restart php8.2-fpm
    

Причина 3: Аварийное падение процесса PHP

Если процесс воркера падает до отправки HTTP-заголовков, Nginx фиксирует сброс соединения.

Запись в /var/log/nginx/error.log:

[error] 1234#0: *1 recv() failed (104: Connection reset by peer) while reading response header from upstream...

Возможные факторы:

  • Превышение memory_limit: Скрипт исчерпал лимит памяти. В логе PHP-FPM появляется запись PHP Fatal error: Allowed memory size of X bytes exhausted.
  • Ошибка сегментации (Segfault): Сбой в расширении PHP. В логе PHP-FPM фиксируется: WARNING: [pool www] child XXX exited on signal 11 (SIGSEGV).
  • Вмешательство OOM Killer: Ядро Linux принудительно завершило процесс из-за дефицита памяти. Проверяется командой:
    dmesg -T | grep -i oom
    

Диагностика и устранение ошибки 504 Gateway Time-out

Код 504 Gateway Time-out означает, что Nginx успешно установил соединение, но не получил ответ от PHP-FPM в течение интервала fastcgi_read_timeout.

[Клиент] ─── HTTP GET ───► [Nginx] ─── FastCGI ───► [PHP-FPM Worker] (Долгий запрос)
                             │                            │
                             │ (Истек fastcgi_read_timeout)│ (Все еще выполняется...)
   ▲                         ▼                            ▼
   └─────── HTTP 504 ────────┘

Причина 1: Длительные операции и рассинхронизация таймаутов

Задержка вызвана тяжелыми SQL-запросами, обработкой больших файлов или зависанием синхронных вызовов к внешним API.

Запись в /var/log/nginx/error.log:

[error] 1234#0: *1 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.0.2.1, server: example.test, request: "POST /export HTTP/1.1", upstream: "fastcgi://unix:/run/php/php8.2-fpm.sock:"

Решение:

  1. Оптимизируйте узкие места в приложении или переведите тяжелые задачи на асинхронные очереди (Redis, RabbitMQ).
  2. Для штатных длительных операций увеличьте лимиты:
    • В Nginx: fastcgi_read_timeout 300s;
    • В PHP-FPM (www.conf): request_terminate_timeout = 300s
    • В php.ini: max_execution_time = 300

Причина 2: Исчерпание свободных воркеров пула

Если все дочерние процессы заняты, входящие запросы становятся в очередь listen.backlog. Если процесс не освобождается вовремя, Nginx закрывает соединение по таймауту.

Запись в логе PHP-FPM (/var/log/php8.2-fpm.log):

WARNING: [pool www] server reached pm.max_children setting (20), consider raising it

Решение:

  1. Проверьте потребление CPU и памяти.
  2. При наличии свободных аппаратных ресурсов увеличьте pm.max_children в www.conf.
  3. Локализуйте медленные запросы, удерживающие воркеры.

Настройка и анализ slowlog

Встроенный журнал медленных запросов PHP-FPM позволяет зафиксировать стек вызовов функций (stack trace) для долгих операций.

Для включения slowlog в www.conf:

; Порог логирования запросов
request_slowlog_timeout = 3s

; Путь к файлу лога
slowlog = /var/log/php-fpm/www-slow.log

; Глубина трейса
request_slowlog_trace_depth = 20

Пример записи в /var/log/php-fpm/www-slow.log:

[01-Feb-2025 14:22:10]  [pool www] pid 4512
script_filename = /var/www/app/public/index.php
[0x00007f8b2c414230] curl_exec() /var/www/app/src/Service/ExternalApi.php:45
[0x00007f8b2c414110] sendRequest() /var/www/app/src/Controller/ApiController.php:28
[0x00007f8b2c414030] handle() /var/www/app/public/index.php:12

В данном примере задержка вызвана выполнением функции curl_exec(). Решением является установка жесткого таймаута на клиентский сетевой запрос (CURLOPT_TIMEOUT).


Чек-лист системных команд для отладки

Для быстрой локализации неполадок используйте следующий набор команд:

# 1. Валидация конфигураций перед перезагрузкой
nginx -t
php-fpm8.2 -t

# 2. Просмотр системных логов в реальном времени
tail -f /var/log/nginx/error.log
tail -f /var/log/php8.2-fpm.log

# 3. Проверка сокетов и очередей соединений
ss -tlpn | grep -E 'php|nginx|9000'
ss -xlpn | grep php

# 4. Проверка прав доступа к файлу сокета
ls -la /run/php/

# 5. Проверка срабатывания OOM Killer ядра
dmesg -T | grep -E -i 'oom|killed process|php-fpm'

# 6. Подсчет числа запущенных воркеров
ps aux | grep php-fpm | grep -v master | wc -l

Часто задаваемые вопросы (FAQ)

1. В чем принципиальная разница между ошибками 502 и 504 в контексте PHP-FPM?

Ошибка 502 Bad Gateway свидетельствует о невозможности подключиться к upstream, сбросе соединения или аварийной остановке процесса воркера. Ошибка 504 Gateway Time-out возникает, когда соединение установлено успешно, но PHP-FPM не сформировал ответ за отведенный интервал fastcgi_read_timeout.

2. Почему Unix-сокет предпочтительнее TCP при размещении на одном сервере?

Unix Domain Socket передает данные в оперативной памяти через механизмы ядра Linux в обход сетевого стека, не требует вычисления контрольных сумм TCP и исключает проблемы с нехваткой свободных локальных портов.

3. Что произойдет, если fastcgi_read_timeout в Nginx меньше max_execution_time в PHP?

Nginx прервет соединение и вернет клиенту ошибку 504. При этом процесс PHP-FPM продолжит исполнение скрипта в фоновом режиме до исчерпания своего лимита времени, нерационально расходуя процессорные ресурсы и память.

4. Как проверить, был ли процесс PHP-FPM остановлен механизмом OOM Killer?

Выполните команду dmesg -T | grep -i oom или просмотрите системный журнал journalctl -k | grep -i oom. При нехватке памяти в выводе появится сообщение вида Out of memory: Killed process <PID> (php-fpm).

5. Как включить страницу /fpm-status для мониторинга пула?

  1. В файле www.conf активируйте параметр:
    pm.status_path = /fpm-status
    
  2. В конфигурацию Nginx добавьте блок:
    location = /fpm-status {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        allow 127.0.0.1;
        deny all;
    }
    
  3. После перезагрузки служб состояние пула проверяется вызовом curl http://127.0.0.1/fpm-status?full.

Заключение

Бесперебойная работа связки Nginx и PHP-FPM строится на корректном распределении системных ресурсов и согласовании сетевых параметров. Для предотвращения большинства типовых инцидентов достаточно придерживаться трех базовых принципов:

  1. Рассчитывать значение pm.max_children на основе реального объема RAM и среднего потребления памяти одним воркером.
  2. Выстраивать сквозную иерархию таймаутов, где лимит Nginx превышает внутренние таймеры PHP.
  3. Использовать slowlog и детальные журналы ошибок для упреждающего обнаружения блокировок и деградации производительности.

Источники

Это авторская статья, основанная на личном опыте и субъективном взгляде автора. Заметили ошибку или битую ссылку? Сообщите нам: info@codesrc.ru - мы оперативно исправим. Спасибо, что помогаете делать блог лучше.
Следите за нами в соцсетях:

Читайте также