Выберите продукт

Nginx 504 Gateway Timeout: таймауты и что с ними делать на практике

504 в Nginx обычно означает, что reverse proxy не дождался ответа от upstream (приложения, PHP-FPM, uWSGI, gRPC). Разбираем логи и тайминги, ключевые proxy/fastcgi/uwsgi/grpc таймауты, 499 и влияние buffering/keepalive, плюс чеклист диагностики за 15 минут.
Nginx 504 Gateway Timeout: таймауты и что с ними делать на практике

504 от Nginx — один из самых раздражающих инцидентов: внешне «упал сайт», а внутри часто всё живо, просто кто-то кого-то не дождался. Почти всегда внизу лежит конкретный таймер: Nginx ждёт бэкенд, клиент ждёт Nginx, балансировщик ждёт Nginx, а приложение ждёт базу.

Ниже — практический разбор типовых источников nginx 504, как отличить Gateway Timeout от «клиент ушёл» (499), какие директивы реально влияют (proxy_read_timeout, fastcgi_read_timeout, uwsgi_read_timeout, grpc_read_timeout) и как крутить таймауты так, чтобы не замаскировать проблему, а стабилизировать сервис.

Что именно означает 504 в Nginx

Код 504 Nginx выдаёт, когда работает в роли шлюза (reverse proxy) и не получил своевременный ответ от «следующего звена» (upstream): приложения, PHP-FPM, uWSGI, gRPC-сервиса или соседнего прокси.

Часто в error log рядом будет ключевая фраза: upstream timed out. Это не «Nginx не отвечает», а «upstream слишком долго молчит».

Увеличение таймаутов иногда оправдано (экспорт, отчёты, long polling), но чаще это временная мера. Если upstream зависает из-за БД, локов, CPU или IO — вы просто дольше ждёте ту же проблему и увеличиваете число висящих соединений.

Быстрый чеклист: куда копать в первую очередь

Чтобы не утонуть в настройках, начните с трёх проверок:

  • Есть ли в error log строка upstream timed out? Если да — это 504 из-за ожидания ответа upstream.

  • Кто разорвал соединение первым? Если в access log 499 — ушёл клиент (браузер/балансировщик/мобильная сеть), а не Nginx.

  • Какая технология upstream? proxy_pass (HTTP), fastcgi_pass (PHP-FPM), uwsgi_pass (uWSGI), grpc_pass (gRPC). Для каждой — свой набор *_timeout.

Если сайт живёт на общем сервере и под нагрузкой регулярно ловит пики по CPU/IO, самый быстрый способ убрать «соседский фактор» — вынести Nginx и приложение на отдельные ресурсы (например, на VDS) и уже там измерять тайминги «в чистом виде».

Пример access log Nginx с таймингами request_time и upstream_response_time

Логи, без которых 504 чинится вслепую

Минимум, который нужен для нормальной диагностики: расширенный access log + error log. Идея простая: вы должны видеть, где именно «сгорает время» — на коннекте, на отправке запроса или на ожидании заголовков/тела ответа.

1) Добавляем тайминги в access log

Если у вас ещё нет лог-формата с таймингами — добавьте. Особенно ценны $request_time и $upstream_response_time: они показывают, сколько времени запрос жил на стороне Nginx и сколько времени «внутри» занял ответ upstream.

log_format timed '$remote_addr - $remote_user [$time_local] '
                 '"$request" $status $body_bytes_sent '
                 'rt=$request_time urt=$upstream_response_time '
                 'uct=$upstream_connect_time uht=$upstream_header_time '
                 'ua="$http_user_agent" '
                 'upstream="$upstream_addr"';

access_log /var/log/nginx/access.log timed;

Как читать:

  • rt близок к вашему таймауту (например, 60.000) и статус 504 — Nginx упёрся в ожидание.

  • urt пустой или «-» — часто означает, что до ответа upstream не дошло (например, коннект/рукопожатие не состоялось).

  • urt большой, а статус 200 — запрос просто долгий (возможно, его обрывает внешний слой, тогда вы увидите 499).

2) Находим конкретное сообщение в error log

Типовая запись:

upstream timed out (110: Connection timed out) while reading response header from upstream

Ключевые слова:

  • while connecting to upstream — проблема на этапе подключения (влияет proxy_connect_timeout).

  • while reading response header from upstream — upstream принял запрос, но не отдал даже заголовки вовремя (влияет proxy_read_timeout/fastcgi_read_timeout/uwsgi_read_timeout/grpc_read_timeout).

  • while sending request to upstream — Nginx долго отправляет запрос upstream (влияет proxy_send_timeout; часто всплывает при медленной сети, перегрузке или большом request body).

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

Главные таймауты Nginx: что за что отвечает

У Nginx несколько таймеров, и путаница здесь — причина «покрутил не то, стало хуже». Важно понимать: read-timeout — это не «весь запрос не дольше N секунд», а ожидание активности на чтении.

proxy_connect_timeout

Максимальное время на установление TCP-соединения с upstream (а в некоторых сценариях — на первичное рукопожатие). Если upstream живой, но перегружен, коннекты могут зависать в очередях (accept queue) и срабатывать как таймаут коннекта.

Симптом: upstream timed out ... while connecting to upstream.

proxy_read_timeout

Таймаут ожидания между операциями чтения от upstream. Если upstream не прислал данные в течение этого времени — Nginx завершит запрос 504.

Для долгих вычислений, где приложение «думает», но ничего не отдаёт (даже заголовки), именно этот таймаут чаще всего и стреляет.

proxy_send_timeout

Таймаут на отправку запроса upstream. Актуально, когда клиент присылает большой request body, Nginx проксирует его дальше, а соединение до upstream медленное или upstream читает медленно.

Аналоги для других upstream

  • PHP-FPM через FastCGI: fastcgi_read_timeout

  • uWSGI: uwsgi_read_timeout

  • gRPC: grpc_read_timeout

Логика у них похожая: сколько Nginx готов ждать данных/ответа от соответствующего протокола.

Почему вместо 504 вы видите 499 (и это тоже про таймауты)

499 — не стандартный HTTP-код, а внутренний статус Nginx: «клиент закрыл соединение». В реальности клиентом может быть:

  • браузер пользователя (закрыл вкладку, ушёл со страницы);

  • мобильная сеть или прокси на пути;

  • внешний балансировщик или ingress (у него свой таймаут ожидания ответа от Nginx);

  • мониторинг/бот, который не готов ждать.

Частая ловушка: вы увеличили proxy_read_timeout до 300s, Nginx перестал отдавать 504, но в логах пошли 499. Это означает: upstream по-прежнему отвечает долго, просто теперь клиент сдаётся раньше, чем Nginx.

При массовых 499 сравнивайте rt из access log с таймаутами внешнего слоя (балансировщик/ingress/CDN). Если rt около 30s, а Nginx ждёт 60s — «режет» именно внешний слой.

Keepalive и «случайные» таймауты под нагрузкой

keepalive_timeout влияет на время удержания idle-соединения с клиентом. Сам по себе он не «лечит» 504, но влияет на нагрузочный профиль: слишком большой keepalive при большом числе клиентов может раздувать количество открытых соединений и потребление памяти и файловых дескрипторов.

Что проверить:

  • хватает ли лимитов на файловые дескрипторы (симптомы: странные обрывы, проблемы с accept);

  • не упираетесь ли в лимиты соединений upstream, если используете keepalive к upstream-пулу;

  • нет ли перекоса, когда клиенты держат много «пустых» keepalive, а рабочим запросам не хватает ресурсов.

Buffering: как он связан с 504 и длинными ответами

Тема buffering важна в двух сценариях: большие ответы и «потоковые» ответы (SSE/long polling/частичные данные).

Proxy buffering

При включённом буферинге Nginx читает ответ upstream быстрее (если может), складывает в буферы или временные файлы и отдаёт клиенту. Это часто полезно: upstream освобождается раньше, а медленный клиент не держит ваше приложение «на поводке».

Но есть обратная сторона: если вы ожидаете периодические небольшие «пульсы» данных, а где-то по пути они буферизуются, клиент может не увидеть данных вовремя. Тогда внешний слой решит, что «тишина» — и оборвёт соединение (часто это выглядит как 499).

FastCGI buffering

Для PHP-FPM похожая история: большие ответы, временные файлы, задержка выдачи клиенту. Сама по себе буферизация не должна вызывать 504, но может маскировать то, что приложение слишком долго молчит до первых байт (а это уже fastcgi_read_timeout).

Схема взаимодействия клиента, Nginx и upstream с буферизацией ответа

Long polling и «вечные» запросы: как согласовать таймауты

Long polling и часть realtime-паттернов — легитимная причина держать запрос открытым долго. Но важно согласовать таймауты на всех слоях:

  • Nginx как reverse proxy (например, proxy_read_timeout);

  • таймауты приложения/воркера (чтобы оно само не убивало запрос раньше);

  • таймауты внешнего балансировщика/ingress;

  • таймауты клиента (JS fetch/XHR, мобильные SDK).

Если хотя бы одно звено настроено на 30s, а остальные на 120s — получите «рваную» картину: часть запросов 499, часть 504, часть успешных, и кажется, что проблема плавающая.

Если у вас gRPC и есть промежуточные прокси, полезно свериться с практиками проксирования HTTP/2: как устроить gRPC-web через прокси.

Практические конфиги: куда добавлять таймауты

Ниже — типовые фрагменты. Подставляйте значения осознанно: сначала измерьте фактические времена ответов и решите, это «нормально долго» или «ненормально зависло».

1) HTTP upstream через proxy_pass

location /api/ {
    proxy_pass http://app_upstream;

    proxy_connect_timeout 5s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;

    proxy_buffering on;
}

2) PHP-FPM через fastcgi_pass

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

    fastcgi_read_timeout 60s;
}

Если у вас «длинные» PHP-скрипты (экспорт/импорт), важно согласовать таймауты и на стороне PHP-FPM (например, лимиты выполнения запроса в пуле), иначе Nginx будет ждать, а воркер уже завершён.

3) uWSGI

location / {
    include uwsgi_params;
    uwsgi_pass unix:/run/uwsgi/app.sock;

    uwsgi_read_timeout 60s;
}

4) gRPC

location /my.service.v1.API/ {
    grpc_pass grpc://grpc_upstream;

    grpc_read_timeout 60s;
}
Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

Почему таймауты «вдруг» стали срабатывать: типовые причины

Если раньше работало, а потом пошли Gateway Timeout, обычно причина не в Nginx как таковом. Частые источники:

  • Деградация базы данных: блокировки, рост времени запросов, вакуум/чекпоинты, нехватка индексов.

  • Очереди/воркеры забиты: запросы стоят в очереди приложения, а Nginx честно ждёт.

  • CPU steal или нехватка CPU на виртуализации: процесс есть, но «квантов» не дают — задержки растут.

  • Диск и IO: логирование, своп, медленный storage, переполнение временных директорий.

  • Сетевые проблемы: потери пакетов, MTU/PMTUD, проблемы с DNS у резолва upstream (если upstream задан именем).

  • Неправильная буферизация для realtime: соединения держатся, но «пульса» нет, внешний слой обрывает.

Как отличить «нужно увеличить таймаут» от «нужно чинить производительность»

Опирайтесь на факты из логов:

  • Если $upstream_response_time стабильно чуть больше текущего таймаута, а бизнес-сценарий легитимно долгий — таймаут можно увеличить, но параллельно подумайте о фоновой обработке (job queue) и отдаче статуса выполнения.

  • Если времена ответа скачут (то 0.2s, то 60s, то 120s) — это почти всегда ресурсная деградация или блокировки. Таймауты не лечат.

  • Если 504 появляется только при пиках — ищите очереди, лимиты воркеров и насыщение CPU/IO.

Мини-ранбук: шаги диагностики 504/499 за 15 минут

  1. Найдите в error log строки upstream timed out и зафиксируйте стадию: connecting, sending, reading.

  2. Сопоставьте по времени с access log и полями rt, urt, uct, uht.

  3. Если много 499 — определите, кто «клиент» (браузер или внешний LB/ingress). Проверьте его таймауты ожидания ответа.

  4. Проверьте здоровье upstream: количество воркеров, очереди, логи приложения на медленные операции.

  5. Если упираетесь в ресурсы сервера — проверьте CPU/IO/память, своп, лимиты файловых дескрипторов.

  6. Только после этого меняйте proxy_read_timeout/fastcgi_read_timeout и фиксируйте эффект по метрикам.

Частые ошибки при «лечении» 504

  • Поднять только proxy_read_timeout и забыть про внешний балансировщик: 504 уйдёт, но вырастут 499.

  • Сделать таймауты слишком большими везде: при реальной деградации получите лавинообразный рост одновременных запросов и усилите проблему.

  • Не логировать тайминги: без $upstream_response_time сложно понять, где именно тратится время.

  • Игнорировать «первые байты»: приложение может считать 2 минуты и только потом прислать заголовки — это классический триггер read-timeout.

Что делать, если проблема упирается в ресурсы

Если вы видите, что 504 коррелирует с ростом нагрузки и upstream физически не успевает, вариантов обычно два:

  • оптимизация: ускорить запросы, разгрузить БД, вынести тяжёлые операции в очередь, добавить кеширование;

  • масштабирование: больше CPU/RAM, быстрый диск, отдельные ноды под приложение/БД.

На практике для продакшена удобнее, когда Nginx и upstream живут на предсказуемых ресурсах, а лимиты процессов и воркеров не упираются в «соседей» по серверу. В этом же месте полезно держать единые таймауты на всем периметре и регулярно проверять их при изменениях (новый ingress, новый CDN, новые настройки LB). Для смежной темы про «долго и безопасно» при переездах и смене точки входа пригодится материал: миграция сайта без простоя.

Итоги

Nginx 504 Gateway Timeout — это симптом несогласованных ожиданий по времени. Лечится не магическим увеличением чисел, а связкой: тайминги в логах → понимание стадии таймаута → настройка нужной директивы (proxy_connect_timeout, proxy_send_timeout, proxy_read_timeout или fastcgi_read_timeout/uwsgi_read_timeout/grpc_read_timeout) → проверка внешних таймаутов и поведения клиентов (включая 499) → работа с первопричиной в upstream.

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

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

Linux shutdown/reboot hangs: systemd debug, umount busy и зависшие процессы OpenAI Статья написана AI (GPT 5)

Linux shutdown/reboot hangs: systemd debug, umount busy и зависшие процессы

Если Linux зависает на shutdown или reboot, чаще всего виноваты stop jobs в systemd, busy-размонтирование, NFS-таймауты, Docker ил ...
IO wait и steal time на VDS: как диагностировать задержки vmstat, iostat, pidstat OpenAI Статья написана AI (GPT 5)

IO wait и steal time на VDS: как диагностировать задержки vmstat, iostat, pidstat

Когда VDS начинает «тормозить», чаще всего причина в iowait, steal time или очередях диска. Ниже — практичная схема диагностики на ...
TLS trust store и ERR_CERT_AUTHORITY_INVALID: как починить цепочку сертификатов и verify error OpenAI Статья написана AI (GPT 5)

TLS trust store и ERR_CERT_AUTHORITY_INVALID: как починить цепочку сертификатов и verify error

ERR_CERT_AUTHORITY_INVALID и openssl verify error обычно сводятся к двум причинам: сервер отдает неполную цепочку (intermediate mi ...