Балансировка нагрузки
Пользователь открывает сайт и не знает, на какой из пяти одинаковых серверов упадёт его запрос. За это отвечает балансировщик нагрузки — он принимает трафик на один адрес и распределяет его по здоровым узлам. Без балансировки горизонтальное масштабирование превращается в список IP, которые клиенту пришлось бы знать самому. Ниже — устройство, виды балансировщиков, настройка HAProxy и алгоритмы выбора узла.
Балансировка нагрузки
Что такое балансировка нагрузки?
Балансировка нагрузки — это процесс распределения входящих запросов между несколькими серверами или узлами системы для обеспечения равномерной загрузки и предотвращения перегрузки отдельных компонентов.
Балансировщик нагрузки — это программное или аппаратное решение, которое управляет потоком входящих запросов и направляет их на доступные серверы или узлы. Он также может выполнять дополнительные функции, такие как мониторинг состояния серверов, проверка работоспособности (health checks) и автоматическое исключение неисправных узлов из пула.

Балансировка работает так:
- клиент отправляет запрос на IP-адрес или доменное имя, которое указывает на балансировщик нагрузки;
- балансировщик принимает запрос и решает, на какой сервер его направить;
- балансировщик использует алгоритм распределения для выбора подходящего сервера;
- перед отправкой запроса балансировщик может проверить состояние сервера;
- запрос передаётся выбранному серверу, который обрабатывает его и возвращает ответ клиенту;
- балансировщик постоянно отслеживает производительность серверов и их доступность - если один из них выходит из строя, балансировщик автоматически перестаёт направлять на него запросы.
Play ITЗагрузка интерактивного демо…
Play ITЗагрузка интерактивного демо…
Виды балансировщиков нагрузки
Балансировщики могут быть программными, аппаратными и облачными.
Аппаратные балансировщики представляют собой специализированное оборудование, разработанное для высокопроизводительной балансировки, к примеру, F5 BIG-IP, Citrix ADC.
Облачные балансировщики же предоставляются облачными провайдерами как сервис. Как мы уже рассматривали в облачных технологиях, их предоставляют техногиганты, соответственно, это AWS Elastic Load Balancer (ELB), Google Cloud Load Balancer, Azure Load Balancer.
Программные балансировщики реализованы как часть программного обеспечения, к примеру, NGINX, HAProxy, Apache HTTP Server, Traefik. Среди функций таких балансировщиков может быть не только распределение запросов между серверами для предотвращения перегрузки, но и мониторинг состояния и шифрование HTTPS-трафика.
HAProxy (High Availability Proxy) — это балансировщик нагрузки с открытым исходным кодом, который используется для распределения входящего трафика между несколькими серверами. Он работает на уровне приложений (L7) и транспортного уровня (L4), что делает его универсальным инструментом для обеспечения высокой доступности, отказоустойчивости и производительности веб-приложений.
NGINX — веб-сервер, с функционалом балансировщика нагрузки. Он работает на уровне приложений (L7) и поддерживает различные алгоритмы балансировки.
Apache HTTP Server предоставляет модуль mod_proxy_balancer, который позволяет использовать его как балансировщик нагрузки. Это решение подходит для небольших проектов или сред, где уже используется Apache в качестве веб-сервера.
Traefik — балансировщик нагрузки, ориентированный на работу в облачных средах и микросервисной архитектуре. Он автоматически обнаруживает сервисы через интеграцию с Docker, Kubernetes, Consul и другими оркестраторами. Может быть избыточным для простых проектов.
AWS Elastic Load Balancer — это облачное решение от Amazon Web Services. Оно предлагает три типа балансировщиков: Application Load Balancer (L7), Network Load Balancer (L4) и Classic Load Balancer (универсальный). ELB автоматически масштабируется и интегрируется с другими сервисами AWS.
| Тип | Уровень OSI | Что видит | Пример |
|---|---|---|---|
| L4 (TCP/UDP) | Транспорт | IP, порт, соединение | NLB, HAProxy mode tcp |
| L7 (HTTP) | Приложение | URL, заголовки, cookies | NGINX, ALB, Traefik |
L7 удобен для маршрутизации /api на один пул, /static на другой и для TLS-терминации. L4 даёт меньшую задержку и подходит для gRPC/TCP, когда не нужно разбирать HTTP-заголовки. Подробнее про HTTP — основа веб-интеграций.
Health check — обязательная часть конфигурации: балансировщик периодически вызывает GET /health (или TCP-connect) и исключает узлы с ошибками из пула, иначе трафик продолжит идти на "мёртвый" инстанс после деплоя.
Настройка и конфигурация балансировщика
Как настроить балансировщик нагрузки?
Рассмотрим на примере HAProxy.
Так, у нас есть приложение, запущенное в нескольких контейнерах, и оркестратор (к примеру, Docker Compose). Важный момент - мы изучим контейнеризацию и работу Docker отдельно, поэтому к этому алгоритму вы сможете вернуться позже.
Установить HAProxy
Установить HAProxy через пакетный менеджер или запустить его в отдельном контейнере через Docker:
docker pull haproxy:latest
Разбор:
docker pull haproxy:latestскачивает образ балансировщика; дальше в контейнер монтируютhaproxy.cfgсfrontend/backend.
Конфигурация
HAProxy работает по конфигурационному файлу haproxy.cfg. Этот файл определяет, как балансировать трафик между серверами (в нашем случае — контейнерами).
Пример файла:
Код ITЗагрузка примера кода…
Разбор:
- Секция
global/defaultsзадаёт логирование, режим HTTP и таймауты connect/client/server для всех последующих секций. frontend http_frontслушает:80и по умолчанию отправляет трафик вbackend http_back.balance roundrobinраспределяет запросы по очереди;server ... checkпомечает узлы с активной проверкой доступности.
Здесь:
- frontend — это "вход" для трафика. Мы говорим HAProxy слушать порт 80.
- backend — это "выход", куда HAProxy будет направлять запросы. Мы указали два сервера (app1 и app2), между которыми будет распределяться нагрузка.
- balance roundrobin — алгоритм балансировки. Запросы будут отправляться по очереди на каждый сервер.
Запуск HAProxy в Docker
Нужно создать Docker Compose файл, чтобы запустить HAProxy вместе с контейнерами.
В файле docker-compose.yml нужно указать соответственно два контейнера с приложением (app1 и app2), запустить их на портах, и также дополнительно запустить haproxy:
Код ITЗагрузка примера кода…
Разбор:
- Сервисы
app1/app2публикуют приложение на хост-портах 8081/8082; клиент снаружи ходит на HAProxy на:80. - Том
./haproxy.cfg:...подставляет конфиг в контейнер балансировщика;depends_onлишь упорядочивает старт, не ждёт readiness. - YAML чувствителен к отступам: каждый уровень вложенности — два пробела; ключи слева определяют структуру конфигурации.
Запуск
Запускаем всё, в нашем случае, через Docker Compose. После этого HAProxy начнёт принимать запросы на порту 80 и перенаправлять их на контейнеры app1 и app2. Похожий паттерн "несколько сервисов + reverse proxy" — стек №11 в галерее Compose.
Проверка работы
В нашем случае, достаточно открыть http://localhost и там можно будет увидеть, что запросы распределяются между контейнерами.
Для более сложных систем (например, Kubernetes) имеется возможность можно настроить HAProxy для автоматического обнаружения контейнеров через Consul.
Пример конфигурации для Consul:
backend http_back
balance roundrobin
server-template app 2 _app._tcp.service.consul resolvers consul resolve-prefer ipv4 check
Разбор:
server-templateразворачивает динамический пул серверов по DNS Consul вместо статического списка IP.resolversиresolve-prefer ipv4задают, откуда HAProxy берёт адреса инстансов при масштабировании.checkисключает из ротации узлы, не прошедшие health check.
Здесь HAProxy будет использовать DNS-записи для поиска доступных серверов.
Примерно по такому алгоритму и выполняется балансировка нагрузки. Готовые контейнеры запускаются довольно легко, если конфигурация корректна.
Алгоритмы балансировки нагрузки
Какие алгоритмы использует балансировка нагрузки?
Round-robin (RR)
Запросы распределяются по очереди между всеми серверами без учёта их загрузки - если есть 3 сервера (A, B, C), запросы будут направлены в порядке A → B → C → A → B → C.
Когда подходит: однородные серверы, короткие запросы одинаковой стоимости, stateless API.
Риск: медленный узел получает ту же долю трафика, что и быстрый — растёт p95 latency всей системы.
Play ITЗагрузка интерактивного демо…
Least Connections (LC)
Запрос направляется на сервер с наименьшим количеством активных соединений, что определяется путём постоянного мониторинга состояния серверов.
Когда подходит: долгие запросы (отчёты, WebSocket), разная скорость обработки на узлах, смешанная нагрузка.
Идея: новый запрос идёт туда, где меньше "висящих" соединений, а не просто по кругу.
Play ITЗагрузка интерактивного демо…
Weighted Round-Robin (WRR)
Аналогично round-robin, но серверам присваиваются веса (например, мощные серверы получают больше запросов). Распределение будет по весу - сервер A (вес 3), сервер B (вес 2), сервер C (вес 1). Распределение будет A → A → A → B → B → C. Веса настраиваются вручную.
Когда подходит: в пуле смешаны машины разной мощности или постепенно вводят новый узел (низкий вес на канареечном сервере).
Play ITЗагрузка интерактивного демо…
Weighted Least Connections (WLC)
Weighted Least Connections (WLC) — это комбинация Least Connections и Weighted Round-Robin. Учитывает как количество активных соединений, так и вес серверов.
Play ITЗагрузка интерактивного демо…
IP Hash
IP Hash распределяет запросы на основе хеша IP-адреса клиента, к примеру, клиент с IP 192.168.1.1 всегда будет направлен на сервер A.
Когда подходит: нужна "липкость" без cookie (простые сессии в памяти узла). Минус: при падении узла клиенты с его IP-пулом переезжают на другой сервер и теряют локальную сессию; за NAT один внешний IP даёт перекос нагрузки.
Play ITЗагрузка интерактивного демо…
Random
Random направляет запросы на случайный сервер. Но здесь может быть неравномерная нагрузка.
Используют редко; на больших объёмах распределение выравнивается, на малых — возможны всплески на один узел.
Play ITЗагрузка интерактивного демо…
См. также
- Масштабирование микросервисных систем
- Контейнеризация — Service и Ingress в Kubernetes
- Сеть и интернет — IP, DNS, TLS
Базовый разбор HTTP и HTTPS находится в отдельной статье — HTTP как основа веб-интеграций.