Вопрос проверяет понимание того, как распределяется трафик в распределенных системах и как обеспечивается отказоустойчивость.
Нагрузка балансируется через компонент, который распределяет входящие запросы между несколькими инстансами сервиса. Балансировщик учитывает доступность инстансов и выбранную стратегию распределения. Обычно используются health checks, чтобы не отправлять трафик на «падающие» узлы. Иногда применяют sticky sessions, если нужно сохранять привязку клиента к одному инстансу.
Балансировка нагрузки — это механизм распределения входящего трафика между несколькими экземплярами сервиса, чтобы система выдерживала больше запросов и продолжала работать при сбоях отдельных узлов.
Балансировка может быть реализована на разных уровнях, и это влияет на возможности и стоимость решения.
Идея:
DNS возвращает разные IP для одного домена (например, round-robin).
Клиенты попадают на разные точки входа.
Ограничения:
DNS-кэширование у клиентов и провайдеров усложняет контроль.
Нельзя быстро «убрать» инстанс из выдачи без учета TTL.
Используется для грубой балансировки между регионами или точками присутствия.
Это балансировка на уровне TCP/UDP.
Что умеет:
Распределять соединения по бэкендам.
Работать очень быстро и с минимальными накладными расходами.
Чего не умеет (обычно):
Не «понимает» HTTP-уровень (URI, headers) как L7.
Примеры логики: распределение TCP-соединений на разные инстансы.
Это балансировка на уровне HTTP/HTTPS (и выше).
Что умеет:
Маршрутизация по пути (/api, /static).
Маршрутизация по хосту (несколько доменов).
Терминация TLS (заканчивает HTTPS на балансировщике).
Повторные попытки (retries) при некоторых ошибках.
Более умные health checks.
Компромиссы:
Дороже по ресурсам.
Сложнее конфигурация.
Чтобы не отправлять запросы на «мертвые» или перегруженные инстансы, применяются проверки здоровья.
Варианты:
TCP-check: порт открыт и соединение устанавливается.
HTTP-check: запрос к /health или /ready.
Глубокая проверка: сервис проверяет зависимости (БД, очередь, диск).
Практика:
Разделять liveness и readiness.
readiness должен отвечать «готов принимать трафик», а не просто «процесс жив».
Если инстанс не проходит check, балансировщик исключает его из пула.
На каждом запросе (или соединении) балансировщик обычно делает следующее:
Принимает входящее соединение/запрос.
Выбирает бэкенд по стратегии.
Проксирует запрос (L7) или перенаправляет соединение (L4).
Учитывает таймауты и ошибки.
При необходимости повторяет запрос на другой инстанс (не всегда безопасно).
Иногда балансировщик «приклеивает» клиента к одному инстансу.
Зачем это нужно:
Если сессия хранится в памяти инстанса.
Если есть состояние, которое не вынесено во внешнее хранилище.
Как делается:
По cookie.
По IP.
Минусы:
Ухудшает равномерность распределения.
При падении инстанса часть клиентов теряет сессию.
Практический вывод: лучше выносить состояние в Redis/DB и избегать sticky, если возможно.
Балансировщик обычно имеет:
connect timeout — время на установку соединения.
read timeout — ожидание ответа.
idle timeout — время простоя соединения.
Retries полезны, но опасны:
Если запрос не идемпотентный (например, создание заказа), повтор может привести к дублям.
Для идемпотентных запросов (GET) retry безопаснее.
Балансировщик часто является ключевой точкой мониторинга:
Метрики: RPS, latency, error rate, распределение по бэкендам.
Логи: access logs, upstream errors.
Трейсинг: прокидывание trace-id.
Это помогает понять, кто «тормозит»: клиент, балансировщик, инстансы или зависимости.
Нагрузка между несколькими инстансами балансируется через DNS и/или L4/L7 балансировщики, которые выбирают бэкенд по стратегии и исключают недоступные узлы через health checks. На практике качество балансировки сильно зависит от корректных readiness-проверок, таймаутов, политики retries и того, вынесено ли состояние из памяти инстансов.