Балансировка нагрузки — оптимальное распределение входящего сетевого трафика между набором бэкенд серверов. Задача балансировщика — распределить между ними нагрузку, чтобы избежать перегрузки и обеспечить доступность, масштабируемость, безопасность и производительность приложения.
Есть разные варианты как типов балансировки так и предназначенного для этого ПО.
Мы рассмотрим на примере Nginx.
Nginx — это веб-сервер, который может использоваться в качестве балансировщика нагрузки, распределяя с помощью различных алгоритмов трафик как для балансировки, так и для отказоустойчивости в случае выхода одного из серверов из строя. Среди других функций можно выделить обратный прокси сервер, HTTP кэш и ряд других. Вернемся к load balancer.
Архитектура нашего балансировщика будет следующая:
Запрос приходит на сервер nginx, далее распределяется между сервером 1 и сервером 2.
Запрос -> nginx —-> server1
|-------> server2
По умолчанию используется round-robin, это метод при котором запросы распределяются равномерно между заданными серверами (учитывая их вес).
Вес (weight) применяется для того, чтобы сервера не простаивали. Каждому серверу назначается приоритет, на основе которого и распределяется трафик. Из плюсов — серверы с большей пропускной способностью гарантированно получат большую нагрузку и не произойдет сбоев.
Можно сделать еще лучше и к параметру weight добавить least_conn, который распределяет новые запросы на сервера с наименьшим количеством соединений в текущий момент.
На выходе получаем баланс нагрузки с минимальным откликом до ресурса.
Такая конфигурация выглядела бы следующим образом
events { worker_connections 1024; }
http {
upstream devopslife_servers { # Задаем upstream
least_conn;
server server1:80 weight=5; # сервер 1
server server2:80 weight=3; # сервер 2
}
server {
listen 80;
location / {
proxy_pass http://devopslife_servers; # балансировка трафика
}
}
}
У нас всего два сервера, мы будем использовать самый простой вариант
events { worker_connections 1024; }
http {
upstream devopslife_servers { # Задаем upstream
server server1:80; # сервер 1
server server2:80; # сервер 2
}
server {
listen 80;
location / {
proxy_pass http://devopslife_servers; # балансировка трафика
}
}
}
Мы можем задать еще много параметров, например добавить третий сервер и прописать
server server3:80 backup;
Который будет использоваться только когда первые два недоступны.
Кроме того
server server3:80 max_fails=1 fail_timeout=70s max_conns=500;
max_fails — количество неудачных попыток, чтобы сервер считался недоступным
fail_timeout — сколько считать сервер недоступным и не посылать на него запросы
max_conns — максимальное количество подключений, по умолчанию стоит безлимитное значение. Если заданное количество превышено, запросы на backend перестают приходить.
Перейдем к практике
Подготовим два простых html файла, чтобы было видно что балансировка работает
nano server1.html
<html><body>Server 1 - devopslife.ru</body></html>
nano server2.html
<html><body>Server 2 - devopslife.ru</body></html>
Запускать будем через Docker
nano docker-compose.yml
version: '3'
services:
# балансировщик
nginx:
image: nginx:1.25.0-alpine
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
ports:
- "8080:80"
# Сервер 1
server1:
image: nginx:1.25.0-alpine
volumes:
- ./server1.html:/usr/share/nginx/html/index.html
# Сервер 2
server2:
image: nginx:1.25.0-alpine
volumes:
- ./server2.html:/usr/share/nginx/html/index.html
Запускаем и проверяем
docker-compose up -d
Переходим по адресу сервера http://ip_address:8080, обновляем страницу несколько раз и видим как происходит балансировка

Завершаем работу
docker-compose down
Photo by Nathan Dumlao on Unsplash