Балансировка нагрузки

Материал из llmdocs — справочник разработчика
Балансировка нагрузки
Назначениемасштабирование и отказоустойчивость
УровниL4 (транспортный), L7 (прикладной)
Алгоритмыround robin, least connections, хеширование, EWMA
ПрограммныеHAProxy, nginx, Envoy, Traefik, IPVS
ОблачныеAWS ELB (ALB/NLB), Google Cloud LB, Yandex NLB/ALB
Связанныеhealth checks, sticky sessions, Anycast

Балансировка нагрузки (англ. load balancing) — распределение входящих запросов или соединений между несколькими экземплярами сервиса. Она решает две задачи: масштабирование (нагрузку, которую не выдержит один сервер, делят несколько) и отказоустойчивость (упавший экземпляр исключается, клиенты продолжают работать). Балансировщик обычно стоит перед группой серверов как единая точка входа и часто совмещает роль обратного прокси: завершает TLS, кэширует, ограничивает частоту запросов.

Уровни балансировки

L4 (транспортный) L7 (прикладной)
Что видит IP-адреса и порты TCP/UDP HTTP-заголовки, пути, cookie, gRPC-методы
Решение принимается на соединение на каждый запрос
Скорость очень высокая, возможна в ядре ниже, нужен разбор протокола
TLS проходит насквозь обычно завершается на балансировщике
Примеры IPVS, AWS NLB, HAProxy mode tcp, Maglev nginx, HAProxy mode http, Envoy, AWS ALB

L7-балансировщик умеет маршрутизировать по содержимому: /api — на один пул, /static — на другой; переключать трафик между версиями (canary, blue-green); повторять неудачные запросы. L4 дешевле и универсальнее — подходит для баз данных, очередей и любых TCP-протоколов.[3]

Алгоритмы

  • Round robin — по кругу; с весами — пропорционально мощности серверов. Простой и предсказуемый вариант по умолчанию.[1]
  • Least connections — на сервер с наименьшим числом активных соединений; хорош для долгих запросов и WebSocket.
  • Power of two choices — выбрать два случайных сервера и отдать запрос менее загруженному; почти так же хорош, как полный перебор, но масштабируется лучше (используется в Envoy).
  • Хеширование по IP клиента, URL или заголовку — один и тот же ключ всегда попадает на один сервер. Консистентное хеширование (кольцо, Maglev) минимизирует перераспределение ключей при добавлении или удалении серверов — важно для кэшей.[5]
  • EWMA / least response time — учитывает задержку ответов, отправляя меньше трафика медленным узлам.

Проверки здоровья

Балансировщик периодически опрашивает серверы (health checks): активно — открывает TCP-соединение или запрашивает GET /healthz — и пассивно, отслеживая ошибки в реальном трафике. Сервер, не прошедший несколько проверок подряд, выводится из ротации и возвращается после восстановления. При плановом выводе узла используют draining: новые соединения на него не идут, а текущие завершаются спокойно.

Состояние и липкие сессии

Если приложение хранит сессию в памяти конкретного сервера, пользователь должен каждый раз попадать на него — это sticky sessions (по cookie балансировщика или хешу IP). Такая привязка мешает равномерному распределению и теряет сессии при падении узла, поэтому предпочтительнее хранить состояние вне серверов — в Redis или базе данных (см. Cookie и сессии). Сервисы без состояния масштабируются горизонтально простым добавлением экземпляров.

Где балансируют

  • DNS — несколько A/AAAA-записей или ответы в зависимости от географии (GeoDNS). Грубо: кэширование DNS мешает быстро убрать упавший узел.
  • Anycast — один IP-адрес анонсируется из многих точек по BGP, трафик идёт в ближайшую; так работают CDN и публичные DNS-резолверы.
  • Выделенный балансировщик — аппаратный (F5, Citrix) или программный (HAProxy, nginx, Envoy) перед группой серверов. Чтобы он сам не стал единой точкой отказа, ставят пару с общим виртуальным IP (keepalived, VRRP).
  • Внутри кластера — в Kubernetes объект Service распределяет трафик между подами через kube-proxy (iptables/IPVS) или eBPF, а Ingress и Gateway API выполняют L7-маршрутизацию (см. Service и Ingress).[4]
  • На стороне клиента — клиент сам получает список экземпляров (из service discovery) и выбирает; так устроены gRPC и service mesh (Envoy-сайдкары в Istio).

Пример: nginx

upstream app {
    least_conn;
    server 10.0.0.11:8000 weight=2;
    server 10.0.0.12:8000;
    server 10.0.0.13:8000 backup;
}

server {
    listen 80;
    location / {
        proxy_pass http://app;
        proxy_next_upstream error timeout http_502;
    }
}

Открытая версия nginx делает только пассивные проверки (max_fails, fail_timeout); активные проверки есть в nginx Plus, HAProxy и Envoy.[2]

См. также

Источники

  1. HAProxy Configuration Manual — balance
  2. nginx — HTTP Load Balancing
  3. Envoy — Load balancing overview
  4. Kubernetes — Service
  5. Google — Maglev: A Fast and Reliable Software Network Load Balancer (NSDI 2016)
  6. RFC 7098 — Using the IPv6 Flow Label for Load Balancing in Server Farms