Перейти к содержанию
Innovialabs

Как настроить балансировку нагрузки в Nginx

Практика3 мин

Коротко

Опишите серверы приложения в блоке upstream, выберите метод (round-robin, least_conn, ip_hash или hash), задайте max_fails и fail_timeout и направьте туда proxy_pass — Nginx сам распределит запросы и уберёт упавший сервер.

Короткий ответ

Балансировка в Nginx строится из двух частей: блока upstream со списком серверов и директивы proxy_pass, которая отправляет туда запросы. Минимальная рабочая конфигурация:

upstream app_backend {
    server 10.0.0.11:3000;
    server 10.0.0.12:3000;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://app_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

По умолчанию запросы идут по кругу (round-robin). Дальше конфигурацию стоит доработать под вашу нагрузку.

Как выбрать метод балансировки

Метод указывается первой строкой внутри upstream.

МетодКак работаетКогда подходит
round-robin (по умолчанию)По очереди, с учётом весовОдинаковые серверы, короткие запросы
least_connНа сервер с наименьшим числом активных соединенийЗапросы разной длительности, WebSocket, загрузки файлов
ip_hashОдин IP клиента — один серверПростая «привязка» клиента без cookie
hash $key consistentСервер выбирается по любому ключуПривязка по cookie, URL или заголовку; кеши
random two least_connДва случайных сервера, из них менее загруженныйНесколько балансировщиков перед одним пулом

Для большинства веб-приложений разумный старт — least_conn.

Пассивные проверки здоровья

Бесплатная версия Nginx проверяет серверы пассивно: по результатам реальных запросов. Параметры задаются у каждого сервера:

upstream app_backend {
    least_conn;
    server 10.0.0.11:3000 max_fails=3 fail_timeout=30s;
    server 10.0.0.12:3000 max_fails=3 fail_timeout=30s;
}
  • max_fails — сколько неудачных попыток за период fail_timeout делает сервер «недоступным».
  • fail_timeout — и окно подсчёта ошибок, и время, на которое сервер исключается.

Что считать ошибкой, решает proxy_next_upstream. По умолчанию это ошибка соединения и таймаут. Можно добавить коды ответа:

proxy_next_upstream error timeout http_502 http_503;
proxy_next_upstream_tries 2;

Осторожно с неидемпотентными запросами: повтор POST на другой сервер может создать дубль заказа. Nginx по умолчанию не повторяет такие запросы, и включать non_idempotent стоит только осознанно. Активные проверки (health_check) есть только в коммерческой NGINX Plus; в бесплатной версии их заменяют внешним мониторингом.

Веса и резервные серверы

Если серверы разные по мощности, используйте weight:

upstream app_backend {
    server 10.0.0.11:3000 weight=3;
    server 10.0.0.12:3000 weight=1;
    server 10.0.0.13:3000 backup;
    server 10.0.0.14:3000 down;
}
  • weight=3 — сервер получает примерно втрое больше запросов.
  • backup — включается, только когда все основные серверы недоступны. Не работает вместе с hash, ip_hash и random.
  • down — сервер временно выведен из ротации, удобно при обслуживании.

Sticky-сессии

Привязка пользователя к серверу нужна, если сессии хранятся в памяти приложения. В бесплатном Nginx есть два способа:

# по IP клиента
ip_hash;

# по cookie сессии
hash $cookie_sessionid consistent;

ip_hash плохо работает, когда много пользователей выходят в интернет через один IP (офис, мобильный оператор). Привязка по cookie точнее. Но лучший вариант — вообще отказаться от sticky-сессий и хранить сессии в Redis или базе: тогда любой сервер может обработать любой запрос, а масштабирование и обновления проходят проще.

Соединения с бэкендом

Чтобы не открывать новое TCP-соединение на каждый запрос, включите keepalive:

upstream app_backend {
    least_conn;
    server 10.0.0.11:3000;
    server 10.0.0.12:3000;
    keepalive 32;
}

location / {
    proxy_pass http://app_backend;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
}

Частые ошибки

  • Забыли передать Host и X-Forwarded-For — приложение видит неверный домен и IP балансировщика.
  • max_fails=0 — проверки отключены, запросы продолжают идти на упавший сервер.
  • Сессии в памяти без привязки — пользователя случайно «разлогинивает».
  • Изменили конфиг и не проверили его: всегда запускайте nginx -t, затем nginx -s reload.

Частые вопросы

Минимум два, иначе балансировать нечего. Но и сам Nginx остаётся единой точкой отказа — для критичных систем ставят два балансировщика с общим плавающим IP или используют балансировщик облачного провайдера.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.