Ошибка 502 Bad Gateway в Nginx + PHP-FPM: Полное руководство по диагностике и исправлению

Ошибка 502 Bad Gateway в Nginx + PHP-FPM: Полное руководство по диагностике и исправлению

Вы управляете сайтом на популярной связке Nginx и PHP-FPM, и внезапно ваши пользователи видят холодящую душу надпись «502 Bad Gateway». Это не просто ошибка — это сигнал о разрыве в самом сердце взаимодействия между веб-сервером и обработчиком PHP. В этой статье мы глубоко погрузимся в причины этой неполадки, разберем пошаговый алгоритм диагностики и предоставим практические решения для возвращения вашего проекта в рабочее состояние.

Что на самом деле означает ошибка 502 Bad Gateway?

Ошибка 502 (Bad Gateway) — это статусный код протокола HTTP, который указывает, что один сервер, действуя в роли шлюза или прокси, получил недопустимый ответ от вышестоящего сервера. В контексте связки Nginx + PHP-FPM, Nginx выступает в роли этого шлюза. Он принимает запросы от клиентов (браузеров), но когда пытается передать запрос на обработку в PHP-FPM (FastCGI Process Manager), что-то идет не так, и он получает либо ошибку, либо вообще никакого ответа. В результате пользователю возвращается страница с кодом 502.

Ключевая аналогия: Представьте, что Nginx — это официант в ресторане, а PHP-FPM — повар на кухне. Ошибка 502 возникает, когда официант (Nginx) приходит на кухню, но не может передать заказ повару (PHP-FPM), потому что кухня перегружена, повар не отвечает или дверь на кухню заблокирована.

Основные причины ошибки 502 в связке Nginx и PHP-FPM

Проблема редко бывает в одной точке. Чаще всего это комплекс факторов, которые нужно последовательно исключать.

1. Проблемы с процессом PHP-FPM

Это самая распространенная категория причин.

  • Исчерпание дочерних процессов (pm.max_children): В конфигурации PHP-FPM задано ограничение на максимальное количество одновременно работающих процессов. При высокой нагрузке все они могут быть заняты, и новым запросам просто некуда будет «пойти».
  • Завершение работы процессов по таймауту (request_terminate_timeout): Если скрипт выполняется дольше, чем задано в этом параметре, PHP-FPM принудительно завершает его. Nginx, не дождавшись ответа, возвращает 502.
  • Критические ошибки в PHP-скриптах: Фатальные ошибки (Fatal Error), исчерпание памяти (Allowed memory size exhausted) или бесконечные циклы могут «убивать» рабочий процесс, не возвращая корректного ответа Nginx.
  • Неправильные права доступа к сокету: Если PHP-FPM работает через Unix-сокет (а не через TCP-порт), у пользователя, от имени которого работает Nginx (часто www-data или nginx), должны быть права на чтение и запись в этот сокет.

2. Проблемы с конфигурацией Nginx

  • Неправильные настройки FastCGI: Ошибки в директивах fastcgi_pass (неверный путь к сокету или IP-адрес порта), fastcgi_read_timeout или fastcgi_send_timeout.
  • Проблемы с буферами: Слишком маленькие значения fastcgi_buffers и fastcgi_buffer_size для больших ответов от PHP.

3. Системные ограничения

  • Нехватка оперативной памяти (OOM Killer): Когда система исчерпывает память, ядро Linux может принудительно завершить процесс PHP-FPM, чтобы спасти систему от краха.
  • Исчерпание лимитов файловых дескрипторов: Каждое соединение использует дескриптор. При их нехватке новые соединения установить не получится.

Пошаговая диагностика и решение

Действуйте последовательно, от простого к сложному.

Шаг 1: Анализ логов — ваш главный инструмент

  1. Логи ошибок Nginx: sudo tail -f /var/log/nginx/error.log. Ищите строки с "upstream timed out", "connect() failed", "Connection refused".
  2. Логи PHP-FPM: Обычно /var/log/php-fpm.log или /var/log/php7.x-fpm.log. Включите логирование в конфиге (php_admin_flag[log_errors] = on). Здесь вы увидите ошибки скриптов.
  3. Системные логи: sudo journalctl -u php-fpm.service -u nginx.service --since "10 minutes ago" или /var/log/syslog.

Совет: Сразу после появления ошибки 502 проверьте логи. Часто там содержится точное указание на причину, например, "Primary script unknown" (проблема с SCRIPT_FILENAME) или "recv() failed (104: Connection reset by peer)" (процесс PHP-FPM аварийно завершился).

Шаг 2: Проверка статуса и конфигурации PHP-FPM

  • Убедитесь, что служба работает: sudo systemctl status php-fpm.
  • Перезагрузите конфигурацию: sudo systemctl reload php-fpm (мягкая перезагрузка).
  • Проверьте конфигурационный пул (например, /etc/php/7.4/fpm/pool.d/www.conf). Обратите внимание на ключевые параметры:
    • pm.max_children — увеличьте, если процессы заняты.
    • pm.start_servers, pm.min_spare_servers, pm.max_spare_servers — настройте под вашу нагрузку.
    • request_terminate_timeout и request_slowlog_timeout — увеличьте для тяжелых скриптов.
    • listen — убедитесь, что путь к сокету или порт совпадает с указанным в конфиге Nginx (fastcgi_pass).

Шаг 3: Проверка конфигурации Nginx

В конфиге вашего сайта (например, в /etc/nginx/sites-available/your_site) проверьте блок location ~ \.php$:

  • fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; — путь должен быть верным.
  • Увеличьте таймауты: fastcgi_read_timeout 300s; (например).
  • Убедитесь в наличии обязательных параметров: fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;.
  • Проверьте синтаксис и примените конфиг: sudo nginx -t && sudo systemctl reload nginx.

Шаг 4: Проверка системных ресурсов

  • Память и нагрузка: free -h, top, htop.
  • Лимиты для процесса PHP-FPM: cat /proc/$(pgrep php-fpm | head -1)/limits | grep "open files".
  • Общие лимиты системы: ulimit -n.

Профилактика ошибок 502

  • Мониторинг: Настройте оповещения о высокой загрузке PHP-FPM или появлении 502 ошибок в логах (например, через Zabbix, Prometheus).
  • Кеширование: Внедрите кеширование на уровне Nginx (FastCGI Cache) для статичного контента, чтобы снизить нагрузку на PHP.
  • Оптимизация кода: Выявляйте и исправляйте «тяжелые» скрипты, используйте профилировщики (Xdebug, Blackfire).
  • Правильный выбор менеджера процессов (pm): Для сайтов с предсказуемой нагрузкой используйте pm = ondemand или static, для высоконагруженных — dynamic с тонкой настройкой.

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

Ошибка 502 появляется только иногда, что делать?

Скорее всего, проблема в периодической пиковой нагрузке, которая исчерпывает пул процессов PHP-FPM (pm.max_children) или системные ресурсы. Внимательно изучите логи в момент возникновения ошибки и увеличьте соответствующие лимиты, а также настройте мониторинг.

Как быстро «починить» сайт, если появилась 502?

Самое быстрое решение — перезапустить PHP-FPM: sudo systemctl restart php-fpm. Это освободит зависшие процессы и очистит память. Однако это временная мера, необходимо найти коренную причину.

В чем разница между restart и reload для PHP-FPM?

restart полностью останавливает и запускает службу, обрывая все текущие соединения. reload плавно перезагружает конфигурацию, запуская новые процессы с новыми настройками и постепенно завершая старые, что предпочтительнее для работающего сайта.

Может ли ошибка 502 быть вызвана проблемами с хостингом?

Да, абсолютно. На shared-хостинге вы можете столкнуться с 502 из-за ограничений, наложенных провайдером (лимиты на процессы, память), или из-за проблем на соседних аккаунтах, влияющих на общие ресурсы сервера. В этом случае необходимо обратиться в техподдержку.