awesome-everything EN
↑ Обратно к восхождению

Сети и протоколы

Health checks, connection draining и slow start

Суть Активные пробы обнаруживают полные отказы; пассивное обнаружение выбросов улавливает тихую деградацию с 5xx в реальном времени; connection draining позволяет завершить запросы в полёте до удаления backend; slow start защищает холодный backend от немедленной полной нагрузки.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на middle-высоте — в небе
◷ 12 min

У backend заполняется диск. Он продолжает принимать TCP-соединения, но каждый HTTP-запрос возвращает 500. Health check L4 (TCP SYN-проба) говорит, что backend здоров. Запросы продолжают маршрутизироваться к нему и завершаться ошибками. Это именно тот пробел, который закрывает пассивный health check.

Активные health checks

LB отправляет пробные запросы к каждому backend с фиксированным интервалом, независимо от реального клиентского трафика.

Типы проб:

  • HTTP GET /healthz — наиболее распространённый; ожидает 200 OK. Обнаруживает отказы на уровне приложения (заполнен диск, база данных недоступна).
  • TCP SYN — лёгкий; просто пытается установить TCP. Обнаруживает полный сетевой или процессный отказ, но пропускает ошибки приложения.
  • gRPC health check — стандарт для gRPC-сервисов (grpc.health.v1.Health/Check).
  • Кастомные UDP-пробы — для не-TCP-сервисов.

Пороги:

  • Помечать unhealthy после 2–3 последовательных отказов.
  • Помечать healthy после 2–3 последовательных успехов.
  • Интервал: 10–30 секунд.

Пробел тихого отказа. Backend, упавший жёстко (процесс убит), обнаруживается TCP SYN. Backend, зависший (thread pool исчерпан, возвращает 500), принимает TCP, но HTTP-запросы завершаются ошибкой — TCP SYN-проба это полностью пропускает. HTTP GET-пробы обнаруживают это, но только если URL пробы упражняет реальную логику приложения, а не тривиальную заглушку, всегда возвращающую 200.

Пассивные health checks и обнаружение выбросов

Вместо отправки проб LB наблюдает реальный трафик. Если backend возвращает повторные 5xx-ошибки или повторные таймауты, он является выбросом.

Обнаружение выбросов Envoy (конфиг по умолчанию):

  • Исключить backend после 5 последовательных 5xx-ответов.
  • Продолжительность исключения начинается с 30 секунд, удваивается при каждом повторном исключении: 30 с → 60 с → 120 с → до ~300 с.
  • LB прекращает маршрутизировать новые запросы к исключённому backend на этот период.

Пассивный vs активный — что каждый обнаруживает:

  • Активный обнаруживает: упавший процесс, сетевой раздел, неправильно маршрутизированный порт.
  • Пассивный обнаруживает: зависания на уровне приложения, исчерпание пула БД, 500-бури из-за GC.
  • Ни один отдельно не достаточен. Используйте оба для эшелонированной защиты.

Флаппинг health checks

Сетевой сбой вызывает 2–3 последовательных отказа активной проверки → backend исключён. Сеть восстанавливается → 2–3 успеха → backend добавлен обратно. Снова сбой → исключён. Это циклирование — флаппинг — вызывает быстрые колебания трафика, когда backend переключается между healthy и unhealthy.

Решение: Увеличить пороги отказа/успеха (требовать 5 последовательных отказов перед исключением). Добавить джиттер к времени проверок, чтобы проверки от нескольких реплик LB не синхронизировались. Экспоненциальный откат исключения Envoy (30 с → 60 с → 120 с) естественно стабилизирует флаппирующий backend: окно исключения расширяется, пока не станет длиннее продолжительности флапа.

Числа health check и draining
Интервал активного health check
10–30 с
Последовательных отказов до исключения
2–3
Последовательных успехов до добавления
2–3
Начальная продолжительность исключения Envoy
30 с
Максимальная продолжительность исключения Envoy
~300 с
Таймаут drain AWS ALB (по умолчанию)
300 с
Drain для коротких HTTP
5–30 с
Drain для WebSocket/SSE
300+ с
Продолжительность медленного старта (типичная)
1–5 мин

Connection draining

При удалении backend (деплой, масштабирование вниз, обслуживание) нельзя резко обрывать активные соединения. Connection draining:

  1. Прекратить маршрутизировать новые запросы на backend.
  2. Позволить запросам в полёте завершиться в пределах таймаута drain.
  3. После таймаута принудительно закрыть оставшиеся соединения.

Таймауты drain:

  • Короткие HTTP-запросы: 5–30 с.
  • Долгоживущие WebSocket / SSE-соединения: 300+ с.
  • AWS ALB по умолчанию: 300 с (настраивается 0–3 600 с).
  • GCP: настраивается 0–3 600 с.

Сторона приложения. При SIGTERM backend должен:

  1. Вызвать close(listening_socket) — прекратить принимать новые соединения.
  2. Завершить все запросы в полёте.
  3. Выйти чисто.

Без draining LB удаляет backend посреди запроса: клиент получает connection reset и вынужден делать retry. С draining запрос завершается нормально и backend тихо выходит.

Slow start / прогрев

Когда backend возвращается в пул после восстановления или первого деплоя, он холодный:

  • Кэши в процессе пусты.
  • Пулы соединений к БД нужно прогреть.
  • Кэши TLS-сессий холодные.

Немедленная отправка 100% трафика вызывает отставание backend под нагрузкой всплеска, что потенциально запускает каскадный отказ.

Решение: Постепенно наращивать трафик — 10% → 50% → 100% в течение 1–5 минут. Envoy поддерживает это через slow_start_window и slow_start_duration. AWS ALB поддерживает через взвешенную target group: новый backend начинает с весом 1 и инкрементируется со временем.

Проследи
1/4

Проследите падение backend, обнаружение health check и плавное возвращение.

1
Step 1 of 4
Backend B2 упал. Активный health check LB зондирует B2 через HTTP GET /healthz каждые 30 с. Что видит LB на первой пробе после падения?
2
Locked
После 2–3 последовательных отказов health check LB помечает B2 unhealthy. Что происходит с новыми запросами vs запросами в полёте?
3
Locked
B2 перезапустился и прошёл 3 последовательных health check. Как трафик нарастает обратно?
4
Locked
B3 всё ещё работает, но его пул БД исчерпан — он возвращает 500 на все запросы. Активный health check (TCP SYN) всё ещё успешен. Что обнаружит проблему?
Граничные случаи

Дизайн endpoint health check. Тривиальный /healthz, всегда возвращающий 200, опасен — он проходит активную пробу даже когда приложение сломано. Хороший health check endpoint проверяет минимальные критические зависимости: можем ли мы подключиться к БД? Можем ли подключиться к кэшу? Возвращает 200 только если backend реально может обслуживать запросы. Но не добавляйте все зависимости: если некритичный downstream-сервис упал, возврат 500 из /healthz излишне исключит backend.

Викторина

Backend принимает TCP-соединения, но его thread pool исчерпан и на каждый HTTP-запрос возвращает 500. Какой тип health check это обнаружит, а какой пропустит?

Викторина

Почему connection draining необходим при удалении backend из пула балансировщика?

Вспомните перед уходом
  1. 01
    Почему нужно использовать и активные, и пассивные health checks, а не только один?
  2. 02
    Что такое флаппинг health check и как экспоненциальный откат исключения Envoy его смягчает?
  3. 03
    Что должен делать backend при SIGTERM для сотрудничества с connection draining?
Итог

Две стратегии health check дополняют друг друга. Активные проверки отправляют пробы (HTTP GET, TCP SYN, gRPC) каждые 10–30 секунд и исключают backend после 2–3 отказов — быстро, но слепы к деградации на уровне приложения, когда TCP всё ещё принимает соединения. Пассивное обнаружение выбросов наблюдает реальный трафик и исключает после повторных 5xx-ответов с экспоненциальным откатом (30 с → 300 с), гасящим флаппинг. Connection draining закрывает разрыв при удалении: новые запросы прекращаются немедленно, запросы в полёте получают 5–30 с (HTTP) или 300+ с (WebSocket) на завершение. Slow start защищает возвращающиеся backends, нарастая трафик с 10% до 100% за 1–5 минут, чтобы холодные кэши и пулы соединений успели прогреться до полной нагрузки.

Связанные уроки
встречается в258
Продолжить восхождение ↑Session affinity, consistent hashing и правильное решение
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.