В цепочке CDN → балансировщик → nginx → приложение каждый узел держит собственные соединения и idle-таймеры. Если один узел пытается повторно использовать соединение, которое сосед уже закрыл, возможны reset, повтор запроса и иногда 502. Причину подтверждают по журналам двух соседних узлов и трассе соединения; одна ошибка клиента этого не доказывает.

HTTP keep-alive позволяет передать несколько запросов по одному соединению. Но «одна цепочка» на схеме — несколько независимых TCP-соединений: клиент–CDN, CDN–балансировщик, балансировщик–nginx и nginx–приложение. Термины keepalive_timeout встречаются в разных продуктах и обозначают разные стороны обмена. У nginx отдельно документированы клиентский keepalive и кэш соединений upstream; не переносите число из одного участка на другой.
Нарисуйте карту соседних участков
| Участок | Кто переиспользует соединение | Где искать таймер | Что записать |
|---|---|---|---|
| Клиент → CDN | Клиент и CDN | Публичный edge | HTTP-версия, idle timeout, код ответа |
| CDN → балансировщик | CDN | Пул origin-соединений CDN | Возраст idle, reset, retry |
| Балансировщик → nginx | Балансировщик | Backend pool балансировщика | Закрытие и новая попытка |
| nginx → приложение | nginx, если upstream keepalive включён | nginx upstream и сервер приложения | Кто первым закрыл idle socket |
Не стоит бездумно выстраивать все таймеры «по возрастанию»: продукт может считать время от разных событий и иметь собственный retry. Практическое правило — соединение не должно оставаться в пуле для повторного использования после того, как сосед считает его закрытым. Точное решение зависит от того, кто инициирует повтор запроса и умеет ли он безопасно открыть новый сокет. Для POST и других запросов с побочным эффектом повтор требует особой осторожности. Семантика соединения HTTP/1.1 описана в RFC 9112.

Карта соединений и владельцев таймаутов
# На nginx: изучить итоговую конфигурацию и логи у точного времени сбоя
nginx -T 2>&1 | grep -E 'keepalive|proxy_http_version|proxy_set_header Connection|proxy_read_timeout'
# Снаружи: сохранить статус и адрес ответа, затем повторить после паузы
curl -sS -o /dev/null -w 'status=%{http_code} ip=%{remote_ip} total=%{time_total}\n' https://example.com/
# Для доказательства reuse/reset нужна трасса соединений или логи обоих соседей.
curl при отдельном запуске обычно создаёт новое соединение; две независимые команды не воспроизводят reuse одного пула. Для лабораторного теста нужен клиент с сохраняемой сессией либо нагрузочный сценарий и контролируемые idle-интервалы. В nginx проверьте proxy_http_version и настройку заголовка Connection по документации proxy. А при сбое после передачи запроса проверьте фазу upstream timeout: таймаут чтения и сброшенный idle-сокет — разные случаи.
Случай из инфраструктуры enterno
При архитектурной проверке 11 ноября 2026 года облачный адрес отдавал 502, а соответствующей строки в error-выборке журнала Traefik на хосте не было. Это указывает, что проверку надо начинать выше по цепочке, но само по себе не доказывает несовпадение keep-alive: журнал Traefik был настроен на запись только ответов 400–599, а отсутствие записи может иметь и другие причины. Поэтому мы не называем инцидент подтверждённым примером idle reset. Для доказательства нужен ID запроса и журналы соседних узлов в одном временном окне. О поиске владельца 502 см. разбор 5xx.
В рабочей системе собирайте timestamp, request ID, адрес origin, статус каждого hop и признаки connection reset by peer или upstream prematurely closed connection. Сопоставьте число ошибок с интервалами простоя и изменением конфигурации. Затем меняйте один таймер или политику reuse, сравнивая до и после. Длительность ожидания клиента проверьте через curl timing, а внешний результат — через проверку сайта.
Как сделан материал
Описание nginx основано на его официальных модулях и RFC 9112. Наблюдение по enterno взято из внутренней записи архитектурной проверки; оно не имеет полной трассы и поэтому не используется как доказательство причины. SerpAPI снимал Google US и Яндекс, Wordstat региона 225 не вернул оценку точной фразы и показал 25 для keepalive timeout nginx.
Частые вопросы
Каждый 502 после простоя — это keep-alive?
Нет. Проверьте источник кода, reset и логи обоих соседних узлов.
Можно ли просто выключить keep-alive?
Это может убрать симптом ценой новых TCP/TLS-соединений и нагрузки. Сначала подтвердите механизм и измерьте эффект.
Почему в nginx чистый лог?
Сбой мог произойти на внешнем узле или не попасть в настроенную выборку. Проверьте журнал и маршрут до nginx.
Какой таймаут должен быть больше?
Сначала выясните, кто хранит соединение для reuse и кто его закрывает. Затем согласуйте соседние таймеры с учётом политики retry.