Top.Mail.Ru
OSEN-НИЙ SAAALEСкидка 50% на виртуальный хостинг и VDS
до 30.11.2025 Подробнее
Выберите продукт

502/504/499 в Nginx и PHP‑FPM: разбор логов, таймауты и рабочие фиксы

Покажу, как диагностировать и чинить 502 Bad Gateway, 504 Gateway Timeout и 499 Client Closed Request в связке Nginx+PHP‑FPM. Разберём логи и тайминги, таймауты и буферы, настройки пула PHP‑FPM, slowlog и рабочие конфиги. Дам понятные шаги и безопасные базовые значения.
502/504/499 в Nginx и PHP‑FPM: разбор логов, таймауты и рабочие фиксы

Коды 502/504/499 в связке Nginx и PHP‑FPM — частые спутники «зависаний» и недоответов. В большинстве случаев причина находится и лечится без смены стека: достаточно грамотно прочитать логи, сверить таймауты и ограничители, понять, где рвётся цепочка — на клиенте, в Nginx, на соединении к upstream или внутри PHP‑FPM/приложения.

Что означают 502, 504 и 499 в контексте Nginx

Коды выглядят похоже, но причины разные:

  • 502 Bad Gateway — Nginx не получил корректный ответ от upstream (PHP‑FPM). Причины: upstream не слушает сокет/порт, умер, перегружен, отдал битые заголовки или оборвал соединение.
  • 504 Gateway Timeout — Nginx не дождался ответа upstream. Причины: долгий PHP‑скрипт, блокировки БД, очередь в PHP‑FPM, слишком маленькие таймауты на стороне Nginx.
  • 499 Client Closed Request — клиент сам закрыл соединение до ответа (мобильная сеть, нетерпеливый пользователь, промежуточный балансировщик/CDN). На сервере запрос часто продолжает выполняться.

Логи: где смотреть и что искать

Диагностика начинается с логов: error_log и access_log Nginx, а также логи и статус PHP‑FPM.

Где логи по умолчанию

Частые пути:

  • Nginx: /var/log/nginx/error.log и /var/log/nginx/access.log
  • PHP‑FPM: /var/log/php-fpm/error.log (или journalctl, если юнит под systemd)

Быстрые команды для последних записей:

tail -n 200 /var/log/nginx/error.log
journalctl -u nginx --since '10 minutes ago'
journalctl -u php-fpm --since '10 minutes ago'

Настройка подробного access_log для upstream

Чтобы понимать, где «тормозит», добавьте формат с таймингами:

log_format upstream_timing '$remote_addr - $request $status '
                          'rt=$request_time urt=$upstream_response_time '
                          'ustat=$upstream_status bytes=$body_bytes_sent';
access_log /var/log/nginx/access_upstream.log upstream_timing;

Как читать поля:

  • $request_time — общее время на запрос (клиент ↔ Nginx ↔ upstream).
  • $upstream_response_time — время ответа upstream. Если -, значит upstream не вызывался.
  • $upstream_status — HTTP‑код от upstream (или несколько кодов, если были ретраи).

Для 504 обычно $upstream_response_time близок к fastcgi_read_timeout, а $upstream_status пустой или 504. Для 502 чаще видно короткий или отсутствующий urt, а в error_log — конкретная причина.

Типичные сообщения в error_log Nginx

connect() failed (111: Connection refused) while connecting to upstream

PHP‑FPM не слушает сокет/порт или умер. Проверьте, запущен ли пул и совпадают ли путь/порт в конфигурации Nginx и PHP‑FPM.

upstream sent too big header while reading response header from upstream

Upstream прислал слишком большие заголовки (часто из‑за огромных cookies). Помогает увеличение fastcgi_buffers/fastcgi_buffer_size или уменьшение размера заголовков на стороне приложения.

upstream prematurely closed connection while reading response header from upstream

Upstream закрыл соединение. Возможные причины: падение воркера PHP‑FPM, превышение request_terminate_timeout или max_execution_time, аварийный kill (OOM).

Access_log Nginx с полями таймингов upstream

Диагностика шаг за шагом

1) Проверяем соединяемость Nginx → PHP‑FPM

Сопоставьте, как Nginx ходит к PHP‑FPM: сокет или TCP‑порт. В Nginx это директива fastcgi_pass. Убедитесь, что ресурс существует и разрешения корректны.

ss -ltnp | grep php-fpm
ls -l /run/php/ | grep fpm.sock

Если используете unix‑сокет, владелец/группа/права должны позволять пользователю Nginx читать/писать. Для TCP проверьте, что порт слушается и не закрыт firewall.

2) Смотрим статус PHP‑FPM и пул

Включите статус и ping в пуле PHP‑FPM:

pm.status_path = /status
ping.path = /ping
ping.response = pong

И пробросьте их через Nginx в отдельные location только из внутренней сети. Это даст статистику по занятым воркерам и очереди.

3) Включаем slowlog и ловим «медленные» скрипты

Slowlog — лучший друг при 504. Включите и задайте порог:

request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/slowlog-www.log

В slowlog вы увидите backtrace: запрос к БД, HTTP‑клиент, файловую операцию, локи в приложении.

4) Ищем признаки OOM и перезапусков

Если система убивает PHP‑FPM из‑за нехватки памяти, Nginx получит 502. Посмотрите dmesg и journalctl на предмет OOM‑killer и crash‑лупов.

5) Репродукция и измерение

Сделайте минимальный скрипт с sleep(N), чтобы проверить связку и таймауты без влияния приложения. Так вы поймёте, кто «режет» долгие ответы — Nginx, PHP‑FPM или внешний балансировщик.

Таймауты: баланс фронта и бэкенда

Клиентские таймауты в Nginx

  • client_header_timeout и client_body_timeout — сколько ждать заголовки/тело от клиента.
  • send_timeout — сколько ждать подтверждения при отправке ответа клиенту.
  • keepalive_timeout — время жизни keep‑alive соединения; слишком мало — лишние переподключения.

FastCGI таймауты

  • fastcgi_connect_timeout — попытка соединения с PHP‑FPM. При малом значении и высоких нагрузках увидите 502.
  • fastcgi_send_timeout — сколько Nginx готов отправлять запрос upstream.
  • fastcgi_read_timeout — сколько Nginx ждёт ответ от PHP‑FPM. Малое значение даёт 504, даже если PHP ещё работает.

Важно: увеличивая fastcgi_read_timeout, проверьте, что на стороне PHP‑FPM не короче request_terminate_timeout, а в php.inimax_execution_time. Иначе PHP‑FPM убьёт запрос раньше, и вы увидите 502/504.

Буферы FastCGI

Если upstream отдаёт большие заголовки/части ответа, увеличьте буферы:

  • fastcgi_buffers и fastcgi_buffer_size — влияют на «upstream sent too big header» и устойчивость при больших Set-Cookie.
  • fastcgi_busy_buffers_size — полезно под нагрузкой при стриминге ответа.

Для небольших проектов достаточно виртуального хостинга, а при росте нагрузки удобнее масштабироваться на VDS. Если планируете переезд без простоя — посмотрите чек‑лист по миграции: переезд сайта без простоя. Оптимизации PHP и сжатия на шаред‑хостинге мы разбирали тут: OPcache и Brotli на shared.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

PHP‑FPM: пул, очередь и «ножницы» производительности

На уровне пулов решаются две проблемы: «не хватает воркеров, растёт очередь» и «воркеры упираются в память/CPU и умирают».

PM‑режим и размеры пула

  • pm = dynamic|ondemand|static — чаще уместны dynamic или ondemand.
  • pm.max_children — максимум воркеров. При очереди и 504/499 на длинных запросах увеличьте в пределах памяти.
  • pm.start_servers, pm.min_spare_servers, pm.max_spare_servers — баланс холодного старта и пиков.
  • pm.max_requests — перезапуск воркеров после N запросов для борьбы с утечками.

Ограничения и убийство «подвисших» запросов

  • request_terminate_timeout — жёсткий предел времени запроса в FPM; не делайте его меньше ожидаемого времени тяжёлых сценариев.
  • php.ini: max_execution_time — ограничение времени выполнения скрипта.
  • memory_limit — слишком высокий провоцирует OOM, слишком низкий — фатальные ошибки и 502.

Slowlog и статус

Включайте slowlog на низком пороге (3–5 секунд) и снимайте статус пула под нагрузкой — так вы увидите, упираетесь ли в pm.max_children и есть ли длинная очередь.

Рабочие сценарии фиксов

Сценарий 1: 504 на отчётах/экспорте

Признаки: $upstream_response_time ≈ таймаут чтения в Nginx, в slowlog — долгие обращения к БД/внешним API.

  • Временно увеличьте fastcgi_read_timeout до значения, покрывающего операцию.
  • Оптимизируйте: индексы БД, лимиты выборок, страничная генерация.
  • Вынесите тяжёлые задачи в фон (очередь), отдавайте быстрый ответ с ID задачи и endpoint прогресса.

Сценарий 2: 502 с «upstream sent too big header»

Признаки: в error_log соответствующее сообщение при входе пользователя/после авторизации.

  • Увеличьте буферы: fastcgi_buffer_size 32k, fastcgi_buffers 16 32k (подберите под свои заголовки).
  • Сократите размер cookies/заголовков в приложении: не храните большие payload в cookie, чистите устаревшие флаги.

Сценарий 3: 502 «connect() failed (111)»

Признаки: PHP‑FPM недоступен по сокету/порту, пиковая нагрузка, высокая очередь.

  • Проверьте соответствие fastcgi_pass и listen пула (путь к сокету или порт).
  • Увеличьте pm.max_children в рамках памяти, включите pm.max_requests, поднимите listen.backlog.
  • Проверьте OOM‑killer; при необходимости снизьте memory_limit и/или добавьте RAM (на VDS это сделать проще).

Сценарий 4: Всплески 499 на мобильном трафике

Признаки: много 499 в access_log на долгих эндпоинтах; пользователи или прокси закрывают соединение раньше ответа.

  • Сократите TTFB: кэшируйте GET, используйте fastcgi‑кэш для детерминированных страниц.
  • Перенесите тяжёлые операции в фон, на фронтенде — прогресс/поллинг.
  • Проверьте таймауты на балансировщике/CDN: они не должны быть короче fastcgi_read_timeout.

Пример базовой конфигурации Nginx (фрагменты)

Минимальные безопасные значения для старта. Подбирайте под свою нагрузку и размер ответов.

log_format upstream_timing '$remote_addr - $request $status '
                          'rt=$request_time urt=$upstream_response_time '
                          'ustat=$upstream_status bytes=$body_bytes_sent';

server {
    listen 80;

    access_log /var/log/nginx/access_upstream.log upstream_timing;

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php-fpm.sock;

        fastcgi_connect_timeout 3s;
        fastcgi_send_timeout 30s;
        fastcgi_read_timeout 60s;

        fastcgi_buffer_size 32k;
        fastcgi_buffers 16 32k;
        fastcgi_busy_buffers_size 64k;
    }

    location = /status { include fastcgi_params; fastcgi_pass unix:/run/php/php-fpm.sock; }
    location = /ping   { include fastcgi_params; fastcgi_pass unix:/run/php/php-fpm.sock; }
}

Конфигурация пула PHP‑FPM в редакторе терминала

Пример пула PHP‑FPM (фрагменты)

Баланс запуска/экономии памяти/стабильности:

[www]
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500

listen = /run/php/php-fpm.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
listen.backlog = 1024

request_terminate_timeout = 120s
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/slowlog-www.log

pm.status_path = /status
ping.path = /ping
ping.response = pong

Как отличить 502 от 504 «по логам»

В access_log с форматом из примера:

  • 504: rt и urt примерно равны и близки к fastcgi_read_timeout.
  • 502: часто urt мало или отсутствует, а в error_log есть сообщение о разрыве/невозможности соединения или «too big header».
  • 499: статус 499 в access_log, urt может быть числом (upstream работал), но клиент ушёл раньше. В error_log это может не отражаться.

Практические советы по снижению риска 499

  • Не держите долгие операции в HTTP‑запросе. Переносите в очередь и возвращайте быстрый ответ.
  • Сократите размер ответа и TTFB: кэш, предзагрузка данных, ленивые вычисления.
  • Проверьте send_timeout и скорость клиента: медленным клиентам полезен стриминг ответа, но следите за таймаутами.
  • В PHP учитывайте обрыв клиента (connection_aborted()) и прекращайте работу, если допустимо.

Чек‑лист перед релизом

  • Включён отдельный access_log с таймингами upstream; считаете перцентили.
  • error_log на уровне warn или error в обычном режиме, info — только для отладки.
  • Статус/пинг PHP‑FPM доступны изнутри инфраструктуры, а не публично.
  • Включён slowlog и настроены пороги request_slowlog_timeout/request_terminate_timeout.
  • Размер пула (pm.max_children) согласован с доступной памятью и профилем запросов.
  • Буферы FastCGI подходят под ваши заголовки и пики.
  • Таймауты Nginx согласованы с ограничениями PHP‑FPM и внешних прокси.

Мини‑FAQ

Почему 502 сразу после деплоя?

Во время перезапуска PHP‑FPM или прогрева OPCache возможна кратковременная недоступность. Делайте graceful reload и health‑checks; держите часть воркеров «тёплыми».

Можно ли «вылечить» 504 только увеличением таймаута?

Только временно. fastcgi_read_timeout поможет пережить пики, но первопричина — медленный код/БД/внешние API или узкий пул PHP‑FPM. Оптимизируйте и масштабируйте.

Откуда берётся 499 и нужно ли паниковать?

Это клиент сам закрыл соединение. Эпизодически — норма. Если растёт на важных эндпоинтах — сокращайте TTFB, добавляйте кэш и фоновую обработку, проверьте таймауты на балансировщике/CDN.

Итоги

502 — про недоступный/падающий upstream или битые заголовки, 504 — про истечение ожидания ответа, 499 — про уход клиента. Отличаем их по таймингам в access_log и сообщениям error_log. Устойчивость достигается балансом таймаутов Nginx/PHP‑FPM, правильным размером пула, slowlog‑диагностикой и архитектурными решениями: кэширование, очереди, разбиение тяжёлых задач. Если проект перерос начальные мощности — переход на VDS упростит масштабирование.

Поделиться статьей

Вам будет интересно

Автобэкапы сайта и БД в S3: restic/borg, шифрование и проверка восстановления OpenAI Статья написана AI Fastfox

Автобэкапы сайта и БД в S3: restic/borg, шифрование и проверка восстановления

Настроим надежные автобэкапы сайта и баз данных в S3/Object Storage: restic и borg, клиентское шифрование, cron-задачи, дампы чере ...
Wildcard SSL для мультисайтов и SaaS: выпуск через DNS‑01, автоматизация и подводные камни OpenAI Статья написана AI Fastfox

Wildcard SSL для мультисайтов и SaaS: выпуск через DNS‑01, автоматизация и подводные камни

Подробный гайд для админов и DevOps: когда нужен wildcard SSL в мультисайтах и SaaS, почему выбирают DNS‑01, как автоматизировать ...
WAF на VDS: ModSecurity + OWASP CRS для Nginx — установка и тюнинг под популярные CMS OpenAI Статья написана AI Fastfox

WAF на VDS: ModSecurity + OWASP CRS для Nginx — установка и тюнинг под популярные CMS

Разворачиваем WAF на Nginx с ModSecurity и OWASP CRS на VDS: установка, запуск в DetectionOnly, подключение правил и безопасные ис ...