Nginx 502 Bad Gateway: почему сайт работает, но Nginx отдаёт 502
Сайт открывался ещё минуту назад. Потом вы обновляете страницу и вместо приложения появляется:
//text
502 Bad Gateway
nginxПри этом сервер доступен. SSH подключается. Nginx запущен. Иногда даже картинки, CSS и JavaScript продолжают загружаться.
Самое неприятное здесь в том, что 502 очень легко принять за поломку самого Nginx.
Хотя Nginx в этот момент может работать совершенно нормально.
Он получил запрос от браузера, попытался передать его другому сервису и не смог получить от него нормальный ответ.
Для обычного сайта цепочка может выглядеть так:
//text
Браузер
↓
Nginx
↓
PHP-FPM
↓
Laravel
↓
MySQLЕсли проблема возникла между Nginx и PHP-FPM, браузер всё равно увидит ошибку Nginx.
Отсюда и появляется странная на первый взгляд ситуация: Nginx работает, а сайт не работает.
Что на самом деле означает 502
Nginx часто выступает посредником.
Например, статический файл он может отдать самостоятельно:
//text
Nginx → style.cssА PHP-запрос передать дальше:
//text
Nginx → PHP-FPM → приложениеДля Node.js схема будет другой:
//text
Nginx → Node.js:3000А для Python-приложения, например:
//text
Nginx → Gunicorn → DjangoВо всех этих случаях Nginx зависит от следующего компонента.
Если тот недоступен, соединение разорвано или ответ оказался некорректным, Nginx может вернуть клиенту 502 Bad Gateway.
Поэтому сама ошибка не отвечает на вопрос «что сломалось».
Она говорит только, что Nginx не смог нормально получить ответ от upstream-сервиса.
Именно поэтому смотреть на страницу с 502 почти бесполезно. Настоящая причина обычно находится в конфигурации и логах.
Первый кандидат PHP-FPM
На сервере с PHP самая распространённая цепочка выглядит примерно так:
//text
Nginx → PHP-FPMНапример, в конфигурации может быть:
//nginx
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}Здесь Nginx должен подключиться к Unix-сокету:
//text
/run/php/php8.3-fpm.sockЕсли PHP-FPM остановился, сокет может исчезнуть.
Тогда происходит примерно следующее:
//text
Браузер
↓
Nginx
↓
/run/php/php8.3-fpm.sock
×Nginx работает, но передать PHP-запрос некуда.
Первое, что стоит проверить:
//bash
sudo systemctl status php8.3-fpmЕсли сервис не запущен:
//bash
sudo systemctl start php8.3-fpmЧтобы PHP-FPM запускался вместе с системой:
//bash
sudo systemctl enable php8.3-fpmНо 8.3 здесь только пример.
На сервере может использоваться PHP 8.2, 8.4 или другая версия. Поэтому не стоит механически копировать команду из чужой инструкции.
PHP-FPM может работать, а сайт всё равно отдавать 502
Это один из самых интересных случаев.
Проверяем:
//bash
sudo systemctl status php8.3-fpmИ получаем:
//text
Active: active (running)PHP-FPM жив.
Nginx тоже жив.
Но сайт продолжает возвращать 502.
В такой ситуации стоит проверить, через какой адрес Nginx пытается связаться с PHP-FPM.
Посмотреть активную конфигурацию можно:
//bash
sudo nginx -TИ найти строку:
//nginx
fastcgi_passДопустим, там указано:
//nginx
fastcgi_pass unix:/run/php/php8.3-fpm.sock;Теперь проверяем каталог:
//bash
ls -l /run/php/Представим, что там есть:
//text
php8.2-fpm.sockа php8.3-fpm.sock нет.
Тогда причина уже практически найдена.
PHP-FPM действительно работает, но Nginx пытается подключиться не туда.
Получается довольно показательная ситуация:
//text
Nginx → работает
PHP-FPM → работает
соединение → настроено неправильно
результат → 502Именно поэтому статус отдельных сервисов не всегда даёт ответ. Нужно проверить, как они связаны между собой.
Иногда проблема появляется после обновления PHP
Это особенно неприятный сценарий.
Допустим, сервер раньше использовал PHP 8.2:
//nginx
fastcgi_pass unix:/run/php/php8.2-fpm.sock;Затем PHP обновили, и теперь работает PHP 8.3.
Сам PHP-FPM запущен:
//text
php8.3-fpm → active (running)Но Nginx всё ещё смотрит на старый сокет:
//text
php8.2-fpm.sockДля системы всё выглядит достаточно хорошо: оба сервиса существуют, но между ними нет правильного соединения.
В результате браузер получает 502.
Поэтому после изменений версии PHP особенно полезно проверить fastcgi_pass.
Если используется proxy_pass
502 вообще не обязательно связан с PHP.
Например, Nginx может проксировать API на Node.js:
//nginx
location /api/ {
proxy_pass http://127.0.0.1:3000;
}Здесь Nginx ожидает приложение на порту 3000.
Если Node.js остановился:
//text
Nginx
↓
127.0.0.1:3000
×никто не принимает соединение.
Результат для клиента снова может выглядеть так:
//text
502 Bad GatewayПроверить, слушает ли кто-нибудь порт 3000, можно:
//bash
sudo ss -lntp | grep :3000Если команда ничего не выводит, на этом порту сейчас нет процесса, который принимает TCP-соединения.
В таком случае бессмысленно бесконечно перезапускать Nginx. Сначала нужно разобраться с приложением, которое должно работать на 3000.
Самая полезная команда при 502 просмотр error.log
Страница с надписью:
//text
502 Bad Gatewayпочти ничего не объясняет.
Лог Nginx может объяснить намного больше.
Например:
//bash
sudo tail -n 100 /var/log/nginx/error.logИли, если нужно наблюдать лог в реальном времени:
//bash
sudo tail -f /var/log/nginx/error.logПосле запуска команды открываем проблемную страницу.
В журнале может появиться сообщение примерно такого характера:
//text
connect() to unix:/run/php/php8.3-fpm.sock failedТеперь ситуация уже совсем другая.
Мы знаем, что Nginx не смог установить соединение с PHP-FPM через конкретный сокет.
Это намного полезнее, чем просто знать о наличии 502.
Другой вариант может выглядеть примерно так:
//text
connect() failed (111: Connection refused)
while connecting to upstreamВ таком случае нужно смотреть, что происходит с upstream-сервисом.
Именно поэтому при диагностике 502 я бы начинал не с перезагрузки сервера, а с журнала ошибок.
Почему перезапуск всего подряд иногда только мешает
Типичный аварийный сценарий выглядит так:
//bash
sudo systemctl restart nginx
sudo systemctl restart php8.3-fpm
sudo rebootПосле этого сайт начинает открываться.
Кажется, проблема решена.
Но что именно произошло?
Неизвестно.
Например, PHP-FPM мог временно зависнуть. Или закончились доступные worker-процессы. Или проблема возникла после изменения конфигурации. Или сервис просто не запустился после обновления.
Перезапуск действительно мог вернуть систему в рабочее состояние, но при этом не объяснил причину.
А если проблема повторится через несколько часов, диагностику придётся начинать практически с нуля.
Поэтому полезнее сначала собрать минимальную информацию:
//bash
sudo systemctl status nginx//bash
sudo systemctl status php8.3-fpm//bash
sudo nginx -t//bash
sudo tail -n 100 /var/log/nginx/error.logИ только после этого перезапускать конкретный сервис, если для этого есть причина.
nginx -t тоже стоит запускать
Иногда проблема появляется после изменения конфигурации.
Проверить её синтаксис можно:
//bash
sudo nginx -tПри корректной конфигурации обычно будет сообщение вроде:
//text
syntax is ok
test is successfulНо важно понимать ограничение этой команды.
Успешный nginx -t не означает, что приложение работает.
Конфигурация может быть синтаксически правильной, а upstream при этом недоступен.
Например:
//nginx
proxy_pass http://127.0.0.1:3000;Nginx понимает эту строку.
Но если приложение на 3000 не запущено, запрос всё равно закончится ошибкой.
Когда 502 появляется только время от времени
Постоянный 502 обычно проще расследовать.
Если сайт вообще не открывается, можно воспроизвести проблему, сразу посмотреть логи и проверить сервисы.
С периодической ошибкой всё сложнее:
//text
10:00 работает
10:15 502
10:16 снова работает
11:40 502Здесь уже стоит смотреть на нагрузку.
Например, PHP-FPM может иметь ограниченное количество worker-процессов:
//ini
pm.max_children = 10Это не означает, что сервер может одновременно выполнять только десять любых операций вообще. Речь идёт о количестве дочерних процессов PHP-FPM, которые могут обслуживать запросы.
Если запросы становятся тяжёлыми и каждый worker долго занят, новые обращения начинают ждать.
Причиной задержек при этом может быть не сам PHP.
Например:
//text
PHP
↓
MySQL
↓
медленный запросили:
//text
PHP
↓
внешний API
↓
долгое ожиданиеВ результате PHP-FPM постепенно забивается долгими запросами.
Поэтому периодические ошибки стоит рассматривать уже шире:
//text
Nginx
PHP-FPM
приложение
база данных
внешние API
CPU
RAM
количество соединенийА что насчёт 504?
502 и 504 действительно легко перепутать, но искать причину нужно немного по-разному.
Упрощённо:
//text
502
↓
Nginx не получил нормального ответа
или не смог нормально связаться с upstreamА:
//text
504
↓
Nginx ждал ответ от upstream
и дождаться его в установленный срок не смогПоэтому при мгновенном 502 логично сначала проверить доступность upstream и способ подключения к нему.
При повторяющемся 504 уже больше внимания стоит уделить времени выполнения запроса, зависшим операциям, базе данных и настройкам таймаутов.
Это упрощённая схема, но для первичной диагностики она достаточно полезна.
Что проверять по порядку
Если сайт внезапно начал отдавать 502, я бы не начинал с перезагрузки сервера.
Сначала проверил бы сам Nginx:
//bash
sudo systemctl status nginxПотом сервис, который должен обрабатывать запросы:
//bash
sudo systemctl status php8.3-fpmЕсли используется другой upstream, проверять нужно уже его.
После этого:
//bash
sudo nginx -tЗатем посмотреть последние ошибки:
//bash
sudo tail -n 100 /var/log/nginx/error.logДля PHP-FPM:
//bash
sudo journalctl -u php8.3-fpm -n 100Если Nginx использует Unix-сокет:
//bash
ls -l /run/php/Если приложение работает через TCP-порт:
//bash
sudo ss -lntpА для конкретного порта:
//bash
sudo ss -lntp | grep :3000После этого уже становится понятно, куда двигаться дальше.
Почему одна ошибка может означать совершенно разные проблемы
Это, пожалуй, главное, что стоит запомнить про 502.
Браузер показывает:
//text
502 Bad GatewayНо за этой одной строкой могут скрываться разные ситуации:
//text
Nginx
↓
PHP-FPM остановленили:
//text
Nginx
↓
неправильный PHP-FPM socketили:
//text
Nginx
↓
Node.js на 3000 не запущенили:
//text
Nginx
↓
upstream перегруженили:
//text
Nginx
↓
проблема возникла при взаимодействии приложения
с базой данных или другим сервисомСнаружи всё это может выглядеть одинаково.
Поэтому 502 это не диагноз.
Это указатель на участок системы, где нужно искать проблему.
Именно поэтому в следующий раз, когда сайт внезапно покажет 502 Bad Gateway, полезнее сначала открыть error.log и посмотреть, какой upstream не ответил и почему.
Иногда одна строка лога сразу объясняет всё:
//text
connect() to unix:/run/php/php8.3-fpm.sock failedИ тогда вместо загадочного «сервер упал» получается вполне конкретная задача: проверить PHP-FPM, сокет и конфигурацию Nginx.
Такой подход обычно экономит гораздо больше времени, чем перезапускать весь сервер в надежде, что ошибка исчезнет сама.
Комментарии
Чтобы оставить комментарий, войдите в аккаунт.