До основного вмісту

Nginx як балансувальник навантаження: налаштування

VDS / VPS · 17.02.2025 · 5 хв читання
Ілюстрація до статті «Nginx як балансувальник навантаження: налаштування»

Базова конфігурація upstream

upstream backend {
    # Round-robin за замовчуванням
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
    server 10.0.0.3:8080 weight=2;  # У 2 рази більше запитів

    # Резервний сервер
    server 10.0.0.4:8080 backup;

    keepalive 32;  # Persistent connections
}

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

Алгоритми балансування

АлгоритмДирективаЗастосування
Round Robin(за замовчуванням)Рівнозначні сервери
Least Connectionsleast_connРізні за навантаженням запити
IP Haship_hashSticky sessions за IP
Hashhash $request_uriКеш-консистентність

Least Connections

upstream backend {
    least_conn;
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
}

Healthcheck (Nginx Plus / nginx_upstream_check_module)

upstream backend {
    server 10.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server 10.0.0.2:8080 max_fails=3 fail_timeout=30s;
}
💡 keepalive 32 у блоці upstream підтримує постійні з'єднання до бекендів — знижує накладні витрати на TCP-хендшейки.

Реальні помилки під час балансування навантаження

Помилка no live upstreams while connecting to upstream зʼявляється, коли всі сервери в блоці upstream позначені як недоступні — Nginx вичерпав ліміт max_fails спроб до кожного з них і не може вибрати бекенд для запиту.

2026/09/12 10:14:02 [error] 1421#1421: *88291 no live upstreams while connecting to upstream, client: 5.44.12.9, server: example.com, request: "GET /api/status HTTP/1.1", upstream: "http://backend"

Спершу перевірте, що бекенди справді відповідають: curl -I http://10.0.0.1:8080 прямо з сервера Nginx. Якщо вони живі, але Nginx все одно вважає їх мертвими — зменшіть fail_timeout або збільшіть max_fails, бо сервер позначається недоступним на весь період fail_timeout після перевищення ліміту помилок.

Помилка upstream sent too big header while reading response header from upstream означає, що бекенд повернув заголовки відповіді більші за буфер, який Nginx виділив під них за замовчуванням.

[error] 1421#1421: *91002 upstream sent too big header while reading response header from upstream, client: 91.200.10.4, server: example.com, upstream: "http://10.0.0.2:8080/"

Рішення — збільшити proxy_buffer_size та proxy_buffers у блоці location, а не в upstream: вони керують буферизацією відповіді проксійованого сервера, а не вибором бекенда.

Sticky sessions: способи та обмеження

Балансувальник без урахування стану добре підходить для stateless-бекендів, але якщо застосунок зберігає сесію в памʼяті процесу, а не в спільному сховищі на кшталт Redis, запити одного користувача мають потрапляти на той самий сервер.

СпосібЯк працюєОбмеження
ip_hashХеш за IP клієнтаЛамається за спільним NAT — багато користувачів з одним IP
hash $cookie_jsessionidХеш за значенням cookieПотребує, щоб cookie вже існувала до першого запиту
sticky cookie (Nginx Plus)Nginx сам ставить cookie з id бекендаНедоступно в open-source версії Nginx

Для більшості проєктів на open-source Nginx практичніше винести сесії у спільне сховище і залишити least_conn без привʼязки до сервера — тоді вихід одного бекенда з ладу не рве сесії його користувачів.

Коли балансування Nginx не підходить

  • Потрібен балансувальник на рівні TCP/UDP для не-HTTP трафіку — тоді використовується блок stream, а не http, з іншим набором директив.
  • Потрібне автоматичне масштабування бекендів без ручної правки конфігу — open-source Nginx не вміє service discovery, потрібен Consul-template, Kubernetes Ingress або Nginx Plus з API.
  • Потрібне балансування між дата-центрами з урахуванням затримки мережі — це задача для GeoDNS або Anycast, а не для upstream-блоку на одному сервері.
  • Єдиний балансувальник Nginx сам стає точкою відмови — для відмовостійкості потрібні щонайменше два вузли з keepalived і спільним VIP.
  • Бекенди потребують TLS-термінації з клієнтськими сертифікатами (mTLS) на кожному вузлі окремо — простіше завершувати TLS один раз на балансувальнику і пускати до бекендів звичайний HTTP усередині приватної мережі.

Перевірка результату

  1. Перевірте синтаксис конфігурації перед перезапуском: nginx -t має повернути syntax is ok та test is successful.
  2. Застосуйте конфіг без розриву активних зʼєднань: systemctl reload nginx.
  3. Переконайтесь, що запити справді розподіляються: кілька разів виконайте curl http://yourdomain.com/ і звірте, який бекенд відповів.
  4. Перевірте відмовостійкість: зупиніть один бекенд і переконайтесь, що запити продовжують оброблятися рештою без помилок 502 на боці клієнта.

Розбір кодів 502 і 504 від бекендів — у статті про діагностику 502 і 504 у Nginx. Обмеження частоти запитів до кожного бекенда налаштовується через limit_req і limit_conn.

Часті питання

Що означає помилка no live upstreams while connecting to upstream і як її усунути?

Вона означає, що всі сервери в блоці upstream позначені недоступними — ліміт спроб max_fails вичерпаний для кожного з них. Спершу перевірте бекенди напряму curl прямо з сервера Nginx: якщо вони живі, зменшіть fail_timeout або збільшіть max_fails, адже сервер лишається позначеним недоступним увесь цей період після перевищення ліміту помилок.

Чому sticky sessions за ip_hash працюють нестабільно для користувачів з одного офісу?

Користувачі за спільним NAT виходять в інтернет з однією і тією самою зовнішньою IP-адресою, і ip_hash спрямовує їх усіх на один і той самий бекенд — при його перевантаженні чи падінні страждає одразу вся група. Надійніше винести зберігання сесії у спільне сховище на кшталт Redis і балансувати без прив'язки до конкретного сервера.

Як додати новий сервер у пул балансування без зупинки обслуговування поточних запитів?

Додайте рядок server з адресою нового бекенда в блок upstream і застосуйте конфігурацію командою systemctl reload — активні з'єднання при цьому не розриваються, на відміну від повного перезапуску служби. Перед включенням у загальний пул варто перевірити новий сервер окремим curl-запитом напряму за його адресою.

Балансувальник Nginx сам може стати точкою відмови — як від цього захиститися?

Так, єдиний вузол з Nginx — це єдина точка відмови незалежно від числа бекендів за ним. Для відмовостійкості потрібні щонайменше два вузли балансування з keepalived і спільною віртуальною IP-адресою, яка перемикається на живий вузол автоматично при падінні основного. Один балансувальник без резерву такої гарантії дати не може.

Чи була стаття корисною?
← Назад до бази знань Поставити питання підтримці