Новинка Виртуальный VDS сервер в Финляндии от 390р
Выберите продукт

Таймауты HTTP в Nginx без сюрпризов: client_body_timeout, proxy_read_timeout и друзья

Таймауты в Nginx — не «магические числа». От них зависят скорость сайта, доля 5xx/4xx в логах и стабильность апстримов. Разложим по полочкам client_body_timeout, proxy_read_timeout, keepalive и родственные директивы, покажем типовые профили и приёмы диагностики.
Таймауты HTTP в Nginx без сюрпризов: client_body_timeout, proxy_read_timeout и друзья

Если в логах периодически всплывают 504 Gateway Time-out, 408 Request Timeout или 499 Client Closed Request, почти всегда дело в некорректных таймаутах. В Nginx их много: одни отвечают за чтение запроса от клиента, другие — за общение с апстримом, третьи — за отправку ответа обратно в браузер. В этой статье я разберу ключевые директивы, покажу безопасные базовые значения и типовые профили для API, загрузок файлов, long‑polling и «медленных клиентов».

Зачем вообще трогать таймауты

Таймауты — это страховка от зависаний и лишней нагрузки. Слишком короткие значения приводят к 504/408 там, где ответ всё же пришёл бы. Слишком большие — держат занятыми воркеры и соединения, копят очереди и растят задержки. Правильный баланс уменьшает ошибки и помогает предсказуемо деградировать при проблемах апстрима или сети.

Правило хорошего тона: глобально задаём умеренные значения, а для специфичных локаций (API, загрузки, стриминг) — адресно переопределяем.

Классы таймаутов в Nginx

Условно разделим на три группы: клиентские (читаем у клиента и отправляем клиенту), таймауты к апстриму (proxy/fastcgi/uwsgi/scgi/grpc) и keepalive‑параметры.

Клиентские

client_header_timeout — ожидаем заголовки запроса от клиента. Если клиент не прислал их вовремя, Nginx вернёт 408. Для обычных сайтов 10–15s достаточно; для мобайла за медленной сетью можно 20–30s.

client_body_timeout — интервал между двумя пакетами тела запроса. Критично для загрузок файлов и POST/PUT. Если пользователь грузит медленно и «замолкает» дольше таймаута — 408. Баланс: 30–60s обычно, при больших загрузках 120–300s.

send_timeout — не общее время ответа, а таймаут неактивности при отправке в сокет клиента. То есть если Nginx не смог записать очередную часть ответа в течение заданного времени (клиент очень медленный) — соединение закрывается. Типично 10–20s. Важно: это не ограничение общей длительности ответа.

Прокси к апстриму

proxy_connect_timeout — время на установку TCP‑соединения с апстримом. Сетевой сбой, SYN/ACK не пришёл — по истечении будет 504. Обычно 3–5s, если апстрим локальный — можно 1–2s.

proxy_send_timeout — таймаут неактивности при отправке запроса апстриму (интервалы записей). Важен при больших телах запросов и медленном апстриме. Обычно 30s; для больших upload‑прокси — до 300s.

proxy_read_timeout — таймаут неактивности чтения ответа от апстрима (интервалы чтений). Главный виновник 504 при долгих вычислениях или стриминге. Для обычного HTML/API 30–60s, для long‑polling/SSE/WebSocket‑апгрейда — минуты и даже часы.

Аналоги для других протоколов: fastcgi_connect_timeout, fastcgi_send_timeout, fastcgi_read_timeout, и т. д.

Keepalive

keepalive_timeout — сколько держать HTTP‑соединение с клиентом в режиме keep‑alive после ответа. Часто 65s как разумный дефолт. Второй параметр, если задан, управляет значением в заголовке Keep-Alive: timeout=.... Можно задавать как keepalive_timeout 65s 20s;.

keepalive_requests — сколько запросов разрешить по одному соединению. Значения 100–1000 нормальны, в зависимости от трафика и поведения клиентов.

keepalive_time — общий лимит жизни keep‑alive‑соединения. Помогает не держать очень старые коннекты бесконечно.

Для апстрима (пул коннектов): upstream { keepalive ...; keepalive_timeout ...; keepalive_requests ...; }. Это снимает накладные расходы на частые TCP‑connect к бэкенду.

Визуальная схема потоков: клиент — Nginx — апстрим и точки срабатывания таймаутов

Базовые безопасные значения

Ниже стартовые пресеты для типичных сайтов. Это не догма; корректируйте под реальные задержки и профиль нагрузки.

# http {} или включаемый конфиг с дефолтами
client_header_timeout 15s;
client_body_timeout 30s;
send_timeout 15s;
keepalive_timeout 65s;
keepalive_requests 1000;
keepalive_time 2m;

# прокси по умолчанию
proxy_connect_timeout 5s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
proxy_buffering on;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;

Что это даёт: быстрый фэйл при недоступности апстрима, терпимость к кратковременным паузам при приёме тела запроса и адекватные ожидания ответа.

Профили под задачи

1) Обычный сайт/лендинг/блог

Короткий TTFB и статический контент, редкие POST‑формы. Близко к «Базовым значениям». Можно даже чуть короче proxy_read_timeout — 15–20s, если всё отдаётся быстро и апстрим рядом. Для ускорения perceived‑скорости можно рассмотреть HTTP 103 Early Hints.

2) REST API с нестабильными апстримами

API нередко общается с внешними сервисами. Здесь лучше минимизировать «зависания» и быстрее отдавать ошибку на ретрай клиента или на очереди задач.

location /api/ {
    proxy_connect_timeout 3s;
    proxy_send_timeout 15s;
    proxy_read_timeout 20s;
    send_timeout 10s;
    # По месту можно включить circuit-breaker логикой proxy_next_upstream
}

Идея в том, чтобы не блокировать воркеры Nginx минутами, если апстрим «тупит». Лучше краткий таймаут и повторная попытка на клиенте или через брокер задач.

3) Большие загрузки файлов

Тут важны два направления: входящий трафик от клиента и исходящий в апстрим (если проксируем upload до бэкенда). Ошибка в типовых настройках — оставить client_body_timeout и proxy_send_timeout слишком короткими.

location /upload/ {
    client_max_body_size 2g;
    client_body_timeout 5m;

    proxy_request_buffering off;  # Стримим в апстрим, без буфера на диск
    proxy_send_timeout 5m;        # Пишем долго в бэкенд
    proxy_read_timeout 2m;        # Ждём ответ бэкенда
}

Если клиенты могут быть «медленными», не забывайте про send_timeout на отдаче ответа и возможное ограничение скорости limit_rate, чтобы не убить канал. При отдаче больших файлов посмотрите материал про HTTP Range и кеширование статики.

4) Long‑polling, SSE и «тихие» стримы

Здесь proxy_read_timeout должен быть большим, иначе Nginx оборвёт соединение в момент, когда бэкенд специально «молчит», удерживая канал открытым.

location /events/ {
    proxy_read_timeout 1h;  # длительная тишина между событиями — это нормально
    proxy_send_timeout 1m;
    # Для SSE добавляют буферы и заголовки, но ключевой параметр — именно proxy_read_timeout
}

Если используете WebSocket‑апгрейд, обычно тоже поднимают proxy_read_timeout до 1h и выше.

Как «читаются» таймауты и что за коды ошибок

Важно понимать, какие коды вернёт Nginx при срабатывании разных таймаутов, и кто виновник.

  • 408 Request Timeout — клиент не прислал заголовки/тело вовремя (client_header_timeout, client_body_timeout).
  • 504 Gateway Time-out — апстрим не ответил вовремя (proxy_connect_timeout, proxy_read_timeout, реже proxy_send_timeout).
  • 499 Client Closed Request — клиент сам закрыл соединение до окончания ответа. Часто результат нетерпеливого браузера или ретраев.
  • 502 Bad Gateway — апстрим оборвал соединение или прислал некорректный ответ (не таймаут).

Ещё два важных момента:

  • send_timeout — это таймаут неактивности записи в клиента, а не «максимальная длительность ответа». Ограничивайте длительность ответов другими способами или продуманной архитектурой.
  • Таймауты — интервальные. Например, proxy_read_timeout 30s означает «между двумя чтениями от апстрима должно пройти не больше 30s», а не «весь ответ должен уложиться в 30s».

Диагностика: лог‑форматы и метрики

Хороший log_format экономит часы на поиске первопричины. Добавьте в access‑лог поля времен апстрима и общего времени запроса.

log_format timed '$remote_addr $request $status '
                 '$request_time $upstream_connect_time '
                 '$upstream_header_time $upstream_response_time';
access_log /var/log/nginx/access_timed.log timed;

$request_time покажет, сколько занимал весь цикл. $upstream_connect_time годится для ловли проблем DNS/сети/handshake к бэкендам. $upstream_response_time — сколько апстрим «думал» или «стримил». Сопоставляйте с кодами 408/499/504 и поймёте, где зажим.

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

Метрики Nginx: request_time и upstream_response_time на панели мониторинга

Подводные камни и антипаттерны

  • «0» как отключение. У send_timeout значение 0 отключит таймаут вовсе — почти всегда плохая идея. Долгие медленные клиенты будут держать воркеры.
  • Одинаковые таймауты для всего. Загрузки, API и стриминг живут по разным правилам. Делайте разные локации и профили.
  • Большие таймауты вместо очередей. Если апстрим реально работает минутами — не лечится таймаутом. Перестройте поток: приём задачи, 202 Accepted, прогресс в фоне, опрос или callback.
  • buffering off без нужды. proxy_request_buffering off и proxy_buffering off усиливают зависимость от скорости клиента/апстрима и увеличивают количество «медленных» коннектов. Включайте осознанно.
  • Забытый upstream keepalive. Частые короткие запросы к бэкенду без пула коннектов — это лишние SYN/ACK и нагрузка. Настройте keepalive в upstream.
  • Нет защиты от тайм‑аутов на отправке. Комбинируйте send_timeout с ограничением скорости (limit_rate) и разумными буферами, чтобы не держать гигабайтные очереди на клиентов с узким каналом.

Практический чек‑лист настройки

  1. Опишите профиль трафика: доля статического, API, загрузок, стриминга. Разведите это по локациям.
  2. Задайте умеренные глобальные дефолты: 15–30s для чтения/отправки, 65s для keep‑alive.
  3. Для upload‑роутов увеличьте client_body_timeout и proxy_send_timeout, подумайте о proxy_request_buffering off.
  4. Для long‑polling/SSE/WebSocket поднимите proxy_read_timeout до минут/часов.
  5. Для REST API к сторонним сервисам сократите proxy_connect_timeout и proxy_read_timeout, чтобы быстрее отдавать ошибку.
  6. Включите расширенный access‑лог с временами апстрима и начинайте наблюдать за реальными распределениями.
  7. Проверьте upstream‑keepalive и лимиты keepalive_requests/keepalive_time для клиентов.
  8. Рассмотрите reset_timedout_connection on, если хотите немедленно освобождать ресурсы при тайм‑аутах клиента.

Набор примеров конфигурации

http {
    client_header_timeout 15s;
    client_body_timeout 30s;
    send_timeout 15s;
    keepalive_timeout 65s 20s;
    keepalive_requests 1000;
    keepalive_time 2m;

    upstream app_backend {
        server 127.0.0.1:9000;
        keepalive 64;
        keepalive_timeout 60s;
        keepalive_requests 1000;
    }

    server {
        listen 80;
        server_name example.test;

        # Быстрый статика‑роут
        location /static/ {
            root /var/www/site;
            expires 30d;
        }

        # API с осторожными таймаутами
        location /api/ {
            proxy_pass http://app_backend;
            proxy_connect_timeout 3s;
            proxy_send_timeout 15s;
            proxy_read_timeout 20s;
            proxy_buffering on;
        }

        # Загрузки
        location /upload/ {
            client_max_body_size 2g;
            client_body_timeout 5m;

            proxy_pass http://app_backend;
            proxy_request_buffering off;
            proxy_send_timeout 5m;
            proxy_read_timeout 2m;
        }

        # Long‑polling/SSE
        location /events/ {
            proxy_pass http://app_backend;
            proxy_buffering off;
            proxy_read_timeout 1h;
            proxy_send_timeout 1m;
        }
    }
}

Полный контроль над конфигурацией Nginx типично доступен на VDS. На шаред‑площадках права ограничены, что усложняет тонкую настройку таймаутов и пулов соединений.

FastFox VDS
Облачный VDS-сервер
Виртуальные серверы с быстрым запуском и гибкой конфигурацией от 390₽ / мес
Доступные локации
Россия Нидерланды Финляндия

HTTP/2 и нюансы

Для HTTP/2 есть дополнительные параметры: http2_idle_timeout и http2_recv_timeout. Первый лимитирует простои, второй — чтение данных. Если у вас много долгоживущих соединений (SSE/графики), проверьте эти значения, чтобы не убить полезные стримы.

Связанные параметры, которые часто путают с таймаутами

  • client_max_body_size — ограничение размера загрузок, не таймаут.
  • proxy_buffers и proxy_busy_buffers_size — буферизация ответа апстрима; влияет на поведение при медленных клиентах, но не задаёт время.
  • limit_rate и limit_rate_after — ограничение скорости отдачи; косвенно влияет на send_timeout, но это не таймауты.

Методика подбора значений

Начните с разумных дефолтов и включите метрики/логи. Снимите распределение $upstream_response_time и $request_time по перцентилям. Если 95‑й перцентиль API укладывается в 600ms, нет смысла держать proxy_read_timeout в 300s — сократите до 10–20s. Для upload‑роутов измерьте фактическое время заливки на «медленном» канале и умножьте на коэффициент запаса 2–3.

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

Итоги

Таймауты в Nginx — это набор рычагов, управляющих тем, сколько мы готовы ждать клиента и апстрим. Осознанный выбор client_body_timeout, proxy_read_timeout, send_timeout и друзей избавляет от 504/408/499, снижает нагрузку и делает систему предсказуемой. Держите умеренные дефолты, настройте адресные профили под сценарии трафика и опирайтесь на логи и перцентили — и сюрпризов станет в разы меньше.

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

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

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

После одновременной остановки всех узлов Galera обычного запуска MariaDB недостаточно. Сначала найдите сервер с последней транзакц ...
CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

Разберём, почему CoreDNS перезапускается или отвечает SERVFAIL, как обнаружить замкнутую пересылку DNS-запросов, проверить доступн ...
Apache Kafka KRaft на VDS: отдельные controller и broker

Apache Kafka KRaft на VDS: отдельные controller и broker

Соберём новый Kafka-кластер без ZooKeeper на шести Linux VDS: три узла controller образуют отказоустойчивый metadata quorum, а три ...