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

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

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

Что такое ошибка 502 Bad Gateway?

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

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

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

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

1. Проблемы с ресурсами сервера

  • Нехватка памяти (RAM/OOM): Самая частая причина. PHP-FPM или система убивают процессы из-за исчерпания оперативной памяти.
  • Перегрузка CPU: Сложные скрипты "вешают" процессы PHP-FPM, и они не успевают ответить в заданный таймаут.
  • Достигнут лимит файловых дескрипторов: Система не может открыть новые сокеты для соединений.

2. Ошибки в конфигурации Nginx и PHP-FPM

  • Неправильные пути к сокету или IP-адресу в директивах fastcgi_pass.
  • Слишком маленькие значения таймаутов (fastcgi_read_timeout, request_terminate_timeout).
  • Некорректные права доступа к Unix-сокету PHP-FPM.

3. Проблемы с PHP-скриптами и расширениями

  • Фатальные ошибки (Fatal Error) в коде, которые аварийно завершают процесс.
  • "Бесконечные" циклы или операции, занимающие огромное количество времени.
  • Конфликты или падения PHP-расширений (например, opcache, xdebug).

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

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

Первое, что нужно сделать — проверить логи. Они часто содержат прямую подсказку.

  1. Логи ошибок Nginx: sudo tail -f /var/log/nginx/error.log. Ищите строки с "upstream timed out", "Connection refused", "Primary script unknown".
  2. Логи PHP-FPM: Обычно в /var/log/php-fpm.log или /var/log/php7.x-fpm.log. Здесь могут быть сообщения о "child ... exited on signal", "seems busy" или ошибки сегментации.
  3. Системные логи: sudo journalctl -xe или /var/log/syslog могут показать, что ядро (OOM Killer) завершило процесс PHP-FPM из-за нехватки памяти.

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

Убедитесь, что служба работает и настроена правильно.

  • Проверьте статус: sudo systemctl status php-fpm (или php7.x-fpm).
  • Перезапустите службу: sudo systemctl restart php-fpm.
  • Сравните путь к сокету в конфиге Nginx (fastcgi_pass unix:/var/run/php/php7.x-fpm.sock;) и в пуле PHP-FPM (listen = /var/run/php/php7.x-fpm.sock).
  • Проверьте права на сокет: ls -la /var/run/php/. Владельцем должен быть пользователь и группа, от которых работает PHP-FPM (например, www-data).

Быстрое решение на время диагностики: Увеличьте таймауты в конфиге Nginx (fastcgi_read_timeout 300s;) и в конфиге пула PHP-FPM (request_terminate_timeout = 300). Это поможет, если проблема в "тяжелых" запросах, но не устранит коренную причину.

Шаг 3: Оптимизация ресурсов PHP-FPM

Часто помогает тонкая настройка пулов процессов. Откройте конфиг пула (например, /etc/php/7.x/fpm/pool.d/www.conf) и отрегулируйте ключевые параметры:

  • pm.max_children: Не ставьте слишком высокое значение. Рассчитывайте по формуле: max_children ≈ (Available RAM) / (Memory per PHP process).
  • pm.start_servers, pm.min_spare_servers, pm.max_spare_servers: Настройте под вашу нагрузку.
  • pm.max_requests: Установите значение (например, 500), чтобы периодически перезапускать процессы и избегать утечек памяти.

Шаг 4: Проверка кода и серверных ограничений

  • Включите логирование ошибок PHP (log_errors = On, error_log = /var/log/php_errors.log) и проверьте их.
  • Увеличьте лимиты памяти для PHP (memory_limit = 256M), если скрипты требуют много ресурсов.
  • Проверьте, не исчерпано ли дисковое пространство (df -h), особенно в разделе /tmp.

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

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

Скорее всего, это проблема с пиковой нагрузкой или утечкой памяти. Проверьте мониторинг нагрузки на CPU и RAM в момент ошибки. Настройте pm.max_requests для циклического перезапуска процессов PHP-FPM.

В логах Nginx ошибка "connect() failed (111: Connection refused)". Что делать?

Это означает, что Nginx не может подключиться к сокету PHP-FPM. Убедитесь, что служба PHP-FPM запущена, а путь к сокету в конфигах Nginx и PHP-FPM абсолютно идентичен. Проверьте права доступа к сокету.

После обновления PHP или установки расширения началась 502 ошибка.

Вероятен конфликт расширений или сбой в конфигурации нового PHP. Отключите недавно установленные расширения, проверьте совместимость версий. Пересоздайте симлинк на сокет после обновления.

Как отличить ошибку 502 из-за нехватки памяти от ошибки таймаута?

Смотрите логи. При нехватке памяти (OOM) в системном логе будет запись от kernel. При таймаутах Nginx запишет "upstream timed out". Также помогает мониторинг в реальном времени командой top или htop.

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

Косвенно. Если PHP-скрипт "висит" в ожидании ответа от медленной или недоступной БД, это может привести к превышению таймаута PHP-FPM и, как следствие, к ошибке 502. Проверьте доступность и производительность вашей СУБД.