Перейти к содержанию

Как разобрать ошибки 502 и 504

Внешняя страница сообщает Bad Gateway или Gateway Timeout, хотя Nginx запущен. В прикладной ветке release-lab-app это означает необходимость посмотреть дальше входного сервера. Между посетителем и программой могут находиться CDN, Nginx и локальный процесс. Один статус не указывает автоматически, какой слой неисправен и почему.

Разберём два условных события: приложение перестало слушать локальный порт, а затем отдельный запрос начал ждать слишком долго. Это учебные сценарии, не настоящие журналы ProfessorWeb. Команды ниже предназначены для разрешённого выделенного стенда и не выполнялись при подготовке курса. Их цель — получить минимально нужные наблюдения, а не перезапускать всё подряд.

Значение статуса и место его появления

По HTTP-семантике 502 связан с некорректным ответом сервера, к которому обратился шлюз или прокси. 504 означает, что нужный ответ от upstream не получен вовремя. Эти определения описывают роль ответившего компонента, а не готовую причину на уровне базы или памяти. Nginx может формировать подобные ответы при своих ошибках обращения к приложению, но аналогичный статус способен вернуть внешний CDN. HTTP Semantics, статусы 502 и 504.

Поэтому сначала сохраняют внешний статус, заголовки, тело и время. Если ответ содержит идентификатор запроса нашего Nginx, можно искать соответствующую запись. Если такого признака нет, ещё нельзя уверенно утверждать, что запрос дошёл до origin. Проверка origin через согласованный маршрут помогает отделить внешний слой. Не стоит считать оформление ошибки доказательством: страницы могут быть заменены или одинаково стилизованы.

Цепочка для учебного приложения

В нашем стенде Nginx передаёт запрос на 127.0.0.1:8000. Там работает либо служба systemd, либо контейнер Compose; одновременно эти варианты не используют один порт. Статическая библиотека обслуживается напрямую и не должна зависеть от этого upstream. Если её старый HTML вдруг получает 502, сначала проверяют выбор виртуального сайта и обработчика: возможно, запрос ошибочно направили в прикладной контур.

Условный сценарий A
Внешний /health → 502
Журнал Nginx → ошибка подключения к 127.0.0.1:8000
Локальный /health → соединение не установлено

Условный сценарий B
Внешний прикладной запрос → 504
Журнал Nginx → ожидание ответа upstream
Локальный быстрый /health → 200

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

Проверка процесса и локального ответа

Для активного systemd-варианта читают статус и journal. Для Compose — состояние контейнера и его журнал. Выбирают соответствующие команды, а не пробуют оба механизма запуска одновременно. Локальный GET к безвредному /health ограничивают временем. Если запрос содержит пользовательские изменения, повторять его ради диагностики без анализа нельзя: приложение могло выполнить действие, хотя внешний прокси не дождался ответа.

sudo systemctl status release-lab-app
sudo journalctl -u release-lab-app --since "10 minutes ago"
curl --max-time 3 --dump-header local.headers \
  --output local-health.json http://127.0.0.1:8000/health

Ожидаемые сведения: работает ли процесс, что он сообщил при запуске, отвечает ли на выбранном адресе. Если порт изменили в контейнере, а Nginx остался прежним, исправляют согласованность адреса. Если приложение постоянно падает из-за отсутствующего паспорта, исправляют подготовку кода или рабочий каталог. Выдача root-прав или открытие порта всему интернету не является необходимым решением этих причин.

Подключение и чтение имеют разные сроки

У Nginx есть отдельные параметры для подключения к upstream и ожидания его ответа. proxy_read_timeout относится к промежутку между операциями чтения, а не обязательно к полной длительности всего ответа. Поэтому интерпретация «запрос обязан закончиться за это число секунд» может быть неверной для потокового ответа. Аналогичные понятия FastCGI имеют свой контекст. Документация Nginx proxy-модуля.

Если медленная операция нормально должна длиться долго, можно согласовать пределы прокси, приложения и клиента. Но сначала выясняют, почему она медленная и сколько ресурсов удерживает. Если задача — сформировать большой экспорт, часто разумнее вынести работу в фоновый процесс и дать статус результата. Бесконечное ожидание каждого worker уменьшает способность обслуживать остальные запросы. Увеличение всех таймаутов может лишь отложить видимый отказ.

Что добавить в журнал

Для прикладного сайта полезны адрес upstream, время соединения, время ответа и статус. Эти поля записывают как строки, потому что при нескольких попытках значения могут быть составными или отсутствовать. Сохраняют также идентификатор запроса, передаваемый приложению. Тогда можно сопоставить событие прокси с прикладным сообщением и номером выпуска. Не выводят секретные параметры или тело запроса ради этого сопоставления.

# Дополнение к полям отдельного прикладного log_format:
'"upstream":"$upstream_addr",'
'"upstream_status":"$upstream_status",'
'"connect_seconds":"$upstream_connect_time",'
'"response_seconds":"$upstream_response_time"'

Фрагмент включается в корректную общую JSON-строку, а не вставляется самостоятельными директивами в server. После будущего применения проверяют итоговый формат и пример записи. Большое время ответа не доказывает конкретную проблему SQL: приложение может ждать внешний API, очередь или другой ресурс. Для базы потребуется отдельное наблюдение запроса и блокировки с соответствующими правами.

Случай PHP-FPM

У PHP-сайта вместо HTTP-порта может использоваться Unix-сокет. Отказ подключения объясняется остановленным FPM, неверным путём или отсутствием нужных прав на сокет. Успешный статический CSS не подтверждает выполнение PHP. Если FPM доступен, но конкретный скрипт ошибается, смотрят его журнал и прикладную причину. Не следует исправлять проблему общим доступом на запись всем пользователям: нужно согласовать реального читателя и права конкретного объекта.

Восстановление и последующий разбор

Если событие началось после нового выпуска и прежний код совместим с базой, возврат может быстро восстановить поведение. Если причина — отказ базы или переполненный диск, старый образ также способен не работать. Решение выбирают по слою, сохраняя журнал и наблюдения до очистки или перезапуска. После действия проверяют тот маршрут, который был неисправен, и внешнее прохождение запроса.

Теперь статусы превращаются в направление разбора: где сформирован ответ, доступен ли upstream, что именно он ожидал и какой компонент изменился. Последний урок объединит всю серию в перенос хостинга, где заранее подготовленные наблюдения и план возврата особенно важны.