Балансировка нагрузки (Load Balancing) — распределение входящих запросов между несколькими экземплярами сервиса. Для системного аналитика тема закрывает вопрос «какой алгоритм и на каком уровне зафиксировать в НФТ и ADR», а не «как настроить NGINX». Выбор стратегии завязан на 08.02 Нефункциональные требования (НФТ) — классификация и стандарты: пропускная способность, доступность, задержка и масштабируемость. Детали паттернов устойчивости и масштабирования — в 03.06.01 Архитектурные паттерны распределённых систем; порядок с ограничением трафика — в 03.06.03 Rate Limiting — управление пропускной способностью.

1. Суть темы

Балансировщик (Load Balancer, LB) стоит между клиентом и пулом бэкенд-экземпляров и решает, к какому экземпляру направить каждый запрос. Цели с точки зрения требований:

ЦельЧто фиксировать в спецификации
Равномерное использование ресурсовАлгоритм и метрика «равномерности» — только для алгоритмов без affinity (см. §3.3–3.4)
Пропускная способностьЧисло экземпляров, лимит соединений на узел, горизонтальное масштабирование без смены клиентского endpoint
ЗадержкаАлгоритм, учитывающий latency (Least Time), если p95/p99 — ключевой KPI
ОтказоустойчивостьИсключение из ротации узлов, не прошедших health check (unhealthy); время обнаружения сбоя
Горизонтальное масштабированиеДобавление/удаление экземпляров без перезагрузки LB и без простоя клиентов

Глобальная vs локальная балансировка. Глобальная — между регионами или AZ (geo-DNS, anycast, cloud global LB): клиент попадает в «ближайший» дата-центр. Локальная — внутри кластера или AZ между экземплярами одного сервиса. В требованиях не смешивайте: «алгоритм Round Robin на ingress» и «geo-маршрутизация пользователя» — разные решения и разные владельцы (DNS vs платформа vs приложение). Для глобальной балансировки отдельно фиксируйте RPO/RTO между регионами и владельца политики geo/DNS.

Опорная цепочка ingress (согласована с 03.06.03 Rate Limiting — управление пропускной способностью; используйте её для трассировки требований):

[Client] → [Global/DNS] → [L4/L7 LB] → [API Gateway] → [Service Mesh / Client-side LB] → [Pod/Instance]
  • Rate Limiting обычно применяют на Gateway (или edge) до выбора конкретного бэкенда — отсекают «шумный» трафик до нагрузки на пул.
  • Балансировка распределяет допущенный трафик между экземплярами; per-instance rate limit без глобального счётчика даёт N× лимит — это тема 03.06.03 Rate Limiting — управление пропускной способностью, не дублируем здесь.

2. Ключевые понятия

2.1. L4 и L7 — критерии выбора

Балансировщики работают на разных уровнях модели OSI; сетевой контекст — 07.07 Сетевые основы (подсети, протоколы и маршрутизация).

ХарактеристикаL4 (Transport)L7 (Application)
Что анализируетIP, порт, протокол TCP/UDPHTTP-заголовки, URL, cookies, gRPC metadata
СкоростьВыше, меньше задержка на проксиНиже из-за разбора содержимого
ПротоколыЛюбые TCP/UDPHTTP/HTTPS, gRPC, WebSocket, SSE
Когда в требованияхБазовая HA, не-TCP-трафик, минимальная задержка проксиМаршрутизация по path/header, sticky по cookie, termination TLS на edge

Правило для SRS: если нужна маршрутизация по URL, tenant, версии API или session affinity через cookie — указывайте L7; если достаточно «раздать TCP-соединения по пулу» — L4. Семантика gRPC load balancing — 03.05.02 Синхронные протоколы (REST, gRPC, GraphQL).

WebSocket / SSE: длительное соединение требует sticky (cookie/hash) или L4 passthrough без разрыва на каждый hop; зафиксируйте idle timeout LB относительно ожидаемой длительности сессии и поведение при reconnect.

2.2. Классификация алгоритмов

ТипПринципПримеры
СтатическиеПравило без учёта текущей загрузки узловRound Robin, Weighted RR, Hash-based, Consistent Hashing
ДинамическиеУчитывают активные соединения, in-flight запросы, latencyLeast Connections, Weighted LC, Least Time, Least Request, P2C

Простой hash vs consistent hashing (для ADR): обычный hash перераспределяет все ключи при изменении размера пула; consistent hashing — только долю ключей, затронутых добавленным/удалённым узлом. В требованиях пишите «consistent hashing», если пул часто меняется (autoscaling, кеш) и недопустима массовая инвалидация; «IP hash / hash by key» — если состав пула стабилен и нужна sticky-сессия без динамики.

2.3. Статические алгоритмы

Round Robin — циклическая очередь. Подходит для однородных stateless-сервисов с короткими запросами одинаковой сложности.

Weighted Round Robin — пропорция по весам. Фиксируйте веса в ADR при разной мощности узлов или canary (10% на новую версию). Веса требуют пересмотра при изменении инфраструктуры; связь с выкатом — 05.04 DevOps и непрерывная поставка — влияние на анализ.

Hash-based (IP Hash, URL Hash, Generic Hash) — детерминированный выбор узла по ключу. Обеспечивает session affinity (sticky sessions): один ключ → один узел. Неравномерность по узлам ожидаема — fairness-метрики к hash не применяют.

Consistent Hashing — hash ring с виртуальными узлами; минимальное перераспределение при scale-out/in. Типичный выбор для распределённых кешей и stateful-маршрутизации при изменяемом пуле. Критерии приёмки — stickiness и поведение при resharding (§3.4), не max/min RPS.

2.4. Динамические алгоритмы

Least Connections — запрос на узел с наименьшим числом активных TCP-соединений (L4/L7). Эффективен, когда запросы разной длительности, но не минимизирует latency напрямую — медленный узел может держать мало соединений, но обрабатывать их долго.

Weighted Least Connections — сравнивают active_connections / weight. Для гетерогенного пула и запросов разной длительности.

Least Time — выбор по среднему времени ответа (TTFB или полный ответ). Используйте в NFR, если KPI — «минимальная задержка», а не «равномерность соединений».

Least Active / Least Request — считают незавершённые вызовы (HTTP in-flight, gRPC outstanding RPC), а не TCP-соединения. На L7 и в RPC (Envoy least request, gRPC client LB) это точнее Least Connections: одно keep-alive соединение может нести много параллельных запросов.

Что считаемТипичный контекстКак писать в NFR
TCP-соединенияL4, long-lived connections«least connections»
HTTP/gRPC in-flightL7, REST/gRPC«least outstanding requests» / «least active»
Latencyp95/p99 как KPI«least response time» / «least time»

P2C (Power of Two Choices) — случайно выбирают два узла, отправляют на менее загруженный. Компромисс между точностью и стоимостью полного сканирования пула; часто в client-side LB и крупных кластерах.

Adaptive / ML-балансировка — агрегирует CPU, память, latency и др. Для большинства корпоративных API достаточно WRR, WLC или Least Request с health checks. Adaptive оправдан при доказанной нестабильности простых алгоритмов и наличии измеримых KPI улучшения; иначе риск scope creep и непроверяемых NFR («адаптивная балансировка с ML» без метрик приёмки).

2.5. Session affinity (sticky sessions)

Sticky sessions нужны, когда состояние хранится на узле, а не во внешнем store.

МеханизмОграничениеЧто указать в требованиях
IP HashЗа CDN/LB/Gateway виден IP прокси, не клиентаКлюч affinity: X-Forwarded-For, cookie, user_id — не «по IP клиента» без проверки топологии
Cookie-based (L7)Стандарт для stateful за reverse proxyИмя cookie, TTL, поведение при отсутствии cookie
Consistent hash by user_idПредсказуемая привязка без cookieКлюч и поведение при смене состава пула

Следствия для приёмки: падение узла → сессии на нём теряются, если нет репликации; нужен ли внешний session store (Redis и т.п.) или переход на stateless + JWT. Альтернатива sticky — stateless-дизайн; это архитектурное решение, не настройка LB.

2.6. Health checks и graceful shutdown

ТипСмыслЧто фиксировать
ActiveLB периодически шлёт probe (HTTP/TCP)Интервал, timeout, порог «N failures → unhealthy», порог «M successes → healthy»
PassiveРешение по ошибкам реального трафика (5xx, timeout, latency spike)Доля ошибок или порог latency для исключения; задержка реакции

Когда passive обязателен в требованиях: probe не покрывает реальный трафик (нестандартные заголовки, только POST), узел «зелёный» по active, но отдаёт 5xx под нагрузкой, или нужна быстрая реакция без ожидания следующего probe. Часто фиксируют combo: active для базового мониторинга + passive для деградации под load.

Flapping: при нестабильном узле задайте hysteresis (разные пороги входа/выхода из пула) и минимальное время в unhealthy, иначе трафик «прыгает» между узлами.

Graceful shutdown / connection draining: при деплое или scale-in узел помечают draining — новые запросы не принимают, текущие дорабатывают. В NFR: «вывод экземпляра из пула ≤ X с без обрыва in-flight запросов»; связь с zero-downtime deploy и canary — 05.04 DevOps и непрерывная поставка — влияние на анализ.

2.7. Место LB в архитектуре

Ниже — детализация уровней опорной цепочки из §1 (не альтернативная схема). Полная цепочка с Global/DNS и Rate Limiting — в §1 и 03.06.03 Rate Limiting — управление пропускной способностью.

[Client] → [External LB] → [API Gateway] → [Microservices]
                              ↓
                    [Service Discovery]
                              ↓
                  [Client-side LB / Mesh]
УровеньРольВладелец в требованияхПримеры
Внешний LBHA, TLS termination, L4/L7 перед gatewayПлатформа / инфраструктураCloud NLB/ALB, hardware LB
API GatewayL7-маршрутизация, affinity, интеграция с RLПлатформа или API-команда (уточнить в ADR)См. 03.05.01 Виды интеграции (точка-точка, ESB, API-led)
Service MeshEast-west между сервисамиПлатформа; политики per-service — команда сервисаSidecar LB — 03.06.01 Архитектурные паттерны распределённых систем, 07.08 Контейнеризация и оркестрация (Docker, Kubernetes)
Client-side LBКлиент выбирает экземпляр по списку из Service DiscoveryКоманда сервиса / интеграционный контрактgRPC, Dubbo

Многослойная балансировка: на пути запроса часто работают несколько LB (ingress RR + mesh/client-side RR). Итоговое распределение сложно предсказать и воспроизвести в тесте. В NFR указывайте алгоритм и метрику на конкретном уровне («fairness на pod за ingress ALB») либо описывайте end-to-end сценарий нагрузочного теста с фиксированной топологией.

Retry на другой узел после ошибки — ответственность gateway/mesh/client, не «алгоритма LB»; в спецификации разводите политику retry (idempotency — 03.06.01 Архитектурные паттерны распределённых систем) и правило выбора узла.

Kubernetes: Service + kube-proxy/IPVS — server-side LB; алгоритмы и ограничения — 07.08 Контейнеризация и оркестрация (Docker, Kubernetes). DNS round-robin без health checks — legacy-anti-pattern: клиент кэширует IP, мёртвые узлы остаются в ротации.

2.8. Сравнительная таблица алгоритмов

АлгоритмТипУчёт нагрузкиУчёт мощностиStickyМетрика приёмкиЛучшее применение
Round RobinСтатическийНетНетНетFairness (RPS)Однородные stateless, короткие запросы
Weighted RRСтатическийНетДаНетДоля трафика по весам / canaryРазномощные узлы, canary
IP / URL HashСтатическийНетНетДаStickiness %Affinity при стабильном пуле
Consistent HashingСтатическийНетНетДаStickiness %; reshardingКеш, частый scale-out/in
Least ConnectionsДинамическийДа (TCP)НетНетFairness (connections)Long-lived / разная длительность
Weighted LCДинамическийДаДаНетFairness с учётом весовГетерогенный пул
Least TimeДинамическийДа (latency)ДаНетp95/p99 latencyKPI — минимальная задержка
Least Request / ActiveДинамическийДа (in-flight)НетНетFairness (in-flight)L7, gRPC
P2CДинамическийДаНетНетFairness (approx.)Большие пулы, client-side
AdaptiveДинамическийДа (много метрик)ДаНет*Заданные KPI ADRТолько при обоснованных KPI

*Adaptive не даёт sticky «из коробки»; affinity задаётся отдельно (hash/cookie), как и для других не-hash алгоритмов.

3. Как применяется в работе аналитика

3.1. Вопросы для сбора требований

ВопросЧто определяет
Stateless или stateful?RR / Least Request vs sticky / external session store
Одинакова ли мощность узлов?Веса (WRR, WLC)
KPI — fairness или latency?Least Connections vs Least Time
Нужна session affinity?Cookie / hash key; не IP Hash за CDN без X-Forwarded-For
Как часто меняется пул?Consistent hashing vs простой hash
Протоколы и уровень?L4 vs L7; WebSocket/SSE — sticky или passthrough — §2.1
Сколько уровней LB на пути запроса?Где измеряем fairness / affinity — один уровень или end-to-end — §2.7
Топология (CDN, gateway, mesh)?Где именно балансируем — 03.01.04 Интерфейсы и интеграционные взаимодействия
Глобальная vs локальная?Geo/DNS, RPO/RTO между регионами, владелец политики
Поведение при падении узла?Health checks (active/passive/combo), draining; retry — gateway/mesh, idempotency — 03.06.01 Архитектурные паттерны распределённых систем
Связка с rate limiting?RL на gateway до LB к бэкендам — 03.06.03 Rate Limiting — управление пропускной способностью
Canary / blue-green?WRR-веса, draining, доля трафика на версию — 05.04 DevOps и непрерывная поставка — влияние на анализ
Кто владелец локального L7?Платформа (shared ingress) vs команда сервиса (dedicated route)

3.2. Где фиксировать в артефактах

АртефактЧто класть
NFR (10.01.12 Шаблон нефункциональных требований (NFR), 02.03.03 Спецификация требований (SRS, Use Case, User Story))Алгоритм на named уровне, L4/L7, health checks (active/passive), время исключения unhealthy, affinity, метрики приёмки, согласованные с алгоритмом
ADR (10.01.13 Шаблон архитектурного решения (ADR))Выбор алгоритма, отвергнутые альтернативы, ключ affinity, trade-off sticky vs stateless, уровень измерения
Интеграционная спецификацияClient-side LB; политика retry/failover на другой узел (gateway/mesh); stacked LB — какой уровень отвечает за fairness

Правило привязки метрики к алгоритму: не смешивайте в одном NFR список алгоритмов с единым KPI fairness. Для RR / Least Request / Least Connections — max/min RPS или connections между здоровыми узлами. Для hash / sticky — stickiness %, hot-spot допустимость, поведение при resharding. Для WRR/canary — доля трафика на версию (± допуск), не fairness между pod одной версии.

3.3. Примеры формулировок

User Story (Least Connections — корректное обоснование):

Как владелец API, я хочу, чтобы запросы распределялись алгоритмом Least Connections, чтобы узлы с меньшим числом активных соединений получали новые запросы и ни один экземпляр не накапливал долгие соединения непропорционально остальным.

User Story (Least Time — если KPI latency):

Как владелец API, я хочу балансировку по наименьшему времени ответа, чтобы p95 latency оставалась в пределах SLA при неоднородной нагрузке на экземпляры.

Пример NFR (fairness — Round Robin / Least Request на ingress):

На уровне L7 ingress ALB сервис orders-api использует алгоритм Least Request. Узел, не прошедший active health check (интервал 5 с, 2 failures → unhealthy), исключается из ротации не более чем за 5 с. При scale-in экземпляр переводится в draining: новые запросы не направляются, in-flight завершаются в течение 30 с. Коэффициент неравномерности между здоровыми узлами (max RPS / min RPS) при steady load однородных запросов ≤ 1,2.

Пример NFR (affinity — consistent hash, отдельный блок):

Для маршрута /api/v1/tenant/* ingress применяет consistent hash по заголовку X-Tenant-Id. ≥ 99% запросов одного tenant_id направляются на один pod при неизменном пуле. При добавлении pod не более 1/N ключей переназначается (N — новый размер пула). Падение pod: запросы затронутых tenant получают 503 с Retry-After; idempotent GET — retry на другой узел через gateway.

Пример NFR (health checks — combo):

Помимо active probe каждые 5 с, балансировщик исключает узел по passive критерию: ≥ 5% ответов 5xx или p95 latency > 2 с за скользящее окно 30 с.

3.4. Критерии приёмки (нагрузочное тестирование)

Критерии оформляйте по 02.04.02 Критерии приёмки; нагрузочная проверка NFR — часть V&V (08.03 Тестирование требований (статическое тестирование), нагрузочное как проверка НФТ).

КритерийКогда применятьЧто проверять
FairnessRR, Least Connections/Request, Least Time — без affinitymax/min RPS или active connections между узлами при однородных запросах; уровень измерения — как в NFR
Traffic split (canary/WRR)Weighted RR, canary, blue-greenДоля запросов на версию/v2 в пределах ±X% от заданного веса
Failover (active)Любой алгоритм с active probeВремя исключения unhealthy; отсутствие 5xx после исключения (с учётом draining)
Failover (passive/combo)Passive или combo в NFRИсключение при инъекции 5xx/latency spike без ожидания следующего active probe; пороги из NFR
LatencyLeast Timep95/p99 при N экземплярах vs baseline одного экземпляра
AffinityHash, cookie, consistent hash≥99% запросов одного ключа на один узел; при падении узла — явное ожидаемое поведение (re-login, failover на store, 503)
ReshardingConsistent hash, autoscalingДоля переназначенных ключей при scale-out/in — в пределах ADR
Stacked LBНесколько уровней балансировкиEnd-to-end сценарий с зафиксированной топологией; не дублировать fairness на каждом hop без обоснования

4. Типовые ошибки и ограничения

ОшибкаПочему плохоКак избежать
Fairness-KPI для hash/stickyНеравномерность по определению; NFR непроверяем или ложно «красный»Метрики stickiness / traffic split — §3.2–3.3
Два независимых RR (ingress + mesh)Распределение непредсказуемо; тесты не воспроизводят prodОдин уровень ответственности в NFR или end-to-end тест — §2.7
Один алгоритм на всёРазные эндпоинты — разная длительность и stateRoute-specific политики на L7
Игнорирование health checksТрафик на мёртвые узлыActive + passive/combo, пороги, hysteresis — §2.6, §3.4
Только active в NFR при нужном passiveProbe «зелёный», реальный трафик падаетCombo или passive для деградации под load — §2.6
Sticky без необходимостиHot spot, сложность failoverStateless + JWT или внешний session store
IP Hash за CDN/gatewayAffinity к одному gateway, не к пользователюCookie или hash по business key
Least Connections «для latency»Алгоритм не оптимизирует время ответаLeast Time или Least Request + мониторинг p95
DNS round-robin как LBНет health checks, кэш DNSНастоящий LB или Service Discovery
Adaptive/ML без KPIНепроверяемое NFRWRR/WLC/Least Request + измеримые метрики
Нет draining при деплоеОбрыв in-flight, 502 при rolloutGraceful shutdown в NFR и runbook — 05.04 DevOps и непрерывная поставка — влияние на анализ
Retry в «алгоритме LB»Размыта ответственность gateway vs сервисRetry/failover — интеграционная спецификация; idempotency — 03.06.01 Архитектурные паттерны распределённых систем
LB без учёта безопасностиDDoS, oversized bodyEdge/WAF, лимиты — 03.05.05 Безопасность API, 08.07 Основы кибербезопасности для системного аналитика

Связи с другими разделами базы

Источники и дополнительные материалы

Книги

  • Chris Richardson — Microservices Patterns (маршрутизация и балансировка в микросервисах)
  • Sam Newman — Building Microservices (Service Discovery, client-side LB)

Онлайн-ресурсы и документация