Практическое руководство по балансировке нагрузки с nginx

Многие разработчики используют nginx только как "обратный прокси + сервер статических файлов", но на самом деле nginx является мощным программным балансировщиком нагрузки. Если вы сами управляете серверами, правильная настройка nginx может значительно повысить стабильность и производительность вашего сервиса.

В этой статье для начинающих и среднепродвинутых разработчиков:

  • Понятие балансировки нагрузки
  • Как настроить балансировку в nginx
  • Алгоритмы (round robin, least_conn, ip_hash и др.)
  • Проверка состояния (health‑check)
  • Часто используемые параметры

1. Что такое балансировка нагрузки?



Балансировка нагрузки (load balancing) — это простое правило:

"Раздавать запросы между несколькими серверами так, чтобы ни один из них не перегружался."

Зачем это нужно?

  1. Защита от всплесков трафика – даже при резком росте запросов один сервер не упадёт.
  2. Масштабирование (scale‑out) – вместо вертикального увеличения ресурсов можно добавить несколько серверов.
  3. Высокая доступность – если один сервер выходит из строя, трафик перенаправляется на остальные.

Где находится nginx?

Обычно схема выглядит так:

Клиент → nginx (балансировщик / обратный прокси) → несколько приложений

nginx принимает запросы и перенаправляет их на один из серверов‑приложений.

2. Основная структура балансировки в nginx

В конфигурации nginx балансировка делится на две части:

  1. upstream‑блок – определяет пул серверов‑бэкендов.
  2. server / location‑блок – указывает, какой upstream использовать для входящих запросов.

Простейший пример:

http {
    upstream app_backend {
        server 10.0.0.101:3000;
        server 10.0.0.102: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;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

Что означает эта настройка?

  • upstream app_backend объединяет два сервера в один пул.
  • proxy_pass http://app_backend; отправляет запросы в пул.
  • Если не указать алгоритм, по умолчанию используется round robin.

3. Алгоритмы балансировки



nginx предлагает несколько стратегий. Выбор зависит от конкретной ситуации.

3.1 round robin (по умолчанию)

upstream app_backend {
    server 10.0.0.101:3000;
    server 10.0.0.102:3000;
}
  • Первый запрос → сервер 1
  • Второй запрос → сервер 2
  • Третий запрос → сервер 1 …

Плюсы: простота, подходит почти для всех случаев. Минусы: не учитывает текущую нагрузку.

3.2 least_conn (наименьшее число соединений)

upstream app_backend {
    least_conn;
    server 10.0.0.101:3000;
    server 10.0.0.102:3000;
}

Запросы идут к серверу с наименьшим количеством активных соединений. Хорошо подходит, если время обработки запросов сильно различается.

3.3 ip_hash (стикки сессии)

upstream app_backend {
    ip_hash;
    server 10.0.0.101:3000;
    server 10.0.0.102:3000;
}

IP клиента хешируется, и запросы всегда идут к одному и тому же серверу. Полезно, если сессии хранятся в памяти сервера.

3.4 Взвешенная балансировка

upstream app_backend {
    server 10.0.0.101:3000 weight=3;
    server 10.0.0.102:3000 weight=1;
}

Сервер 1 получает 3‑й раз больше запросов, чем сервер 2.

4. Health‑check и обработка отказов

Чтобы балансировщик был «умным», нужно автоматически исключать неработающие серверы.

4.1 max_fails / fail_timeout

upstream app_backend {
    server 10.0.0.101:3000 max_fails=3 fail_timeout=30s;
    server 10.0.0.102:3000 max_fails=3 fail_timeout=30s;
}
  • max_fails=3 – после 3 последовательных неудачных попыток сервер считается нерабочим.
  • fail_timeout=30s – в течение 30 секунд запросы к этому серверу не отправляются.

Неудачей считаются, например, ответы 502/503/504 или потеря соединения.

4.2 proxy_next_upstream

location / {
    proxy_pass http://app_backend;
    proxy_next_upstream error timeout http_502 http_503 http_504;
}

При указанных ошибках запрос пробрасывается на следующий сервер.

5. Практический пример: балансировка простого веб‑сервиса

Предположим, у нас два Node.js‑сервера на порту 3000:

  • 10.0.0.101:3000
  • 10.0.0.102:3000

5.1 Конфигурация nginx

http {
    upstream app_backend {
        least_conn;
        server 10.0.0.101:3000 max_fails=3 fail_timeout=30s;
        server 10.0.0.102:3000 max_fails=3 fail_timeout=30s;
    }

    server {
        listen 80;
        server_name myservice.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;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_read_timeout 60s;
            proxy_connect_timeout 5s;
            proxy_send_timeout 10s;
        }
    }
}

После перезагрузки nginx:

  • Все запросы к myservice.com распределяются по серверам с наименьшим числом соединений.
  • Если сервер несколько раз подряд не отвечает, он временно исключается.

6. HTTPS (SSL‑termination) + балансировка

В продакшене почти всегда используется HTTPS. Самый распространённый паттерн – завершать TLS в nginx.

http {
    upstream app_backend {
        least_conn;
        server 10.0.0.101:3000;
        server 10.0.0.102:3000;
    }

    server {
        listen 443 ssl;
        server_name myservice.com;
        ssl_certificate     /etc/letsencrypt/live/myservice.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/myservice.com/privkey.pem;

        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;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }

    server {
        listen 80;
        server_name myservice.com;
        return 301 https://$host$request_uri;
    }
}
  • Между клиентом и nginx – HTTPS.
  • Между nginx и приложением – HTTP (обычно внутри сети).

7. Сессии: нужны ли sticky‑sessions?

Раньше сессии хранились в памяти сервера, поэтому требовалось, чтобы один и тот же пользователь всегда попадал на один и тот же сервер. ip_hash решал эту задачу.

Сегодня чаще используют:

  • Redis и другие внешние хранилища для сессий.
  • JWT‑базированные stateless‑сервисы.

Если возможно, уберите состояние из приложения – балансировщик будет только распределять трафик, а масштабирование станет проще.

8. Часто используемые настройки оптимизации

8.1 keepalive

upstream app_backend {
    least_conn;
    server 10.0.0.101:3000;
    server 10.0.0.102:3000;
    keepalive 32;
}

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

keepalive 32; сохраняет до 32 соединения с каждым бэкендом, уменьшая задержки.

8.2 Буферы и таймауты

location / {
    proxy_pass http://app_backend;
    proxy_buffering on;
    proxy_buffers 16 16k;
    proxy_busy_buffers_size 64k;
    proxy_read_timeout 60s;
    proxy_send_timeout 60s;
}

Небольшие таймауты могут привести к 504‑ошибкам, поэтому подбирайте их под реальный трафик.

9. Пошаговый план внедрения

  1. Шаг 1 – Добавьте nginx как обратный прокси к существующему серверу.
  2. Шаг 2 – Клонируйте приложение, добавьте второй сервер, настройте upstream.
  3. Шаг 3 – Включите health‑check (max_fails, fail_timeout) и мониторинг.
  4. Шаг 4 – Выберите алгоритм балансировки, настройте keepalive, буферы, таймауты.

Итоги

nginx – это не просто обратный прокси, а полноценный балансировщик нагрузки. С помощью upstream, выбора алгоритма, health‑check и HTTPS‑termination вы можете быстро повысить стабильность и производительность вашего сервиса.

image