ГоловнаСтаттіРозповсюджені системи

Балансування навантаження: Round Robin, Least Connections & Power of Two Choices

Як round robin, найменша кількість з’єднань, вагові політики та маршрутизація за вибором з двійки в степені утримують черги серверів короткими — і чому сліпі політики створюють гарячі точки.

mysimulator teamОновлено — червень 2026≈ 8 хв читання▶ Відкрити симуляцію

Чому одна черга перемагає багато

Лoадер балансер розташований перед групою бекенд серверів і вирішує для кожного вхідного запиту, який сервер обробляє. Мета звучить просто — розподілити роботу — але політику, яку ви обираєте, змінює затримку кінця навіть у порядку магніту, навіть коли загальний пропускна здатність однаково виглядає на панелі. Основний принцип з теорії черг полягає в тому, що одна спільна черга, яка живить багато серверів, перемагає одну приватну чергу для кожного сервера, оскільки приватна черга може залишатися порожньою позаду повільного запиту, тоді як інша черга підвантажує. Більшість реальних балансерів наближають спільну чергу без фактичного її побудови, маршрутизуючи на основі живих сигналів від кожного бекенда.

Round robin є найпростішою політикою: запит 1 йде до сервера A, запит 2 до B, запит 3 до C, потім назад до A. Це безпосередньо, дешево та справедливо за кількістю — але воно не враховує, як довго кожен запит фактично триває. Якщо сервер B обробляє повільне запитування з генерації звітів, round robin продовжує надсилати йому нову роботу за розкладом, і його черга зростає, тоді як A та C порівняно неактивні.

жива демонстрація · пов'язана симуляція● LIVE

Наименьшее количество соединений и взвешенные варианты

Наименьшее количество соединений исправляет слепоту, направляя каждый новый запрос на сервер, у которого в данный момент меньше активных запросов. Для этого балансеру необходимо отслеживать количество активных соединений, но это дает реальную выгоду: медленные серверы естественным образом получают меньше новых задач, потому что их счетчик активных соединений остается высоким.

score(server) = activeConnections(server) / weight(server) следующий запрос -> argmin(score) по всем здоровым серверам Взвешенная круговая ротация — соответствующее решение для круговой ротации: сервер с весом 3 получает три запроса, в то время как сервер с весом 1 получает один запрос, циклически переходя по фиксированному шаблону вместо того, чтобы зависеть от текущей нагрузки. Это хорошее компромиссное решение, когда вы заранее знаете относительную мощность и не хотите затрат на учет активных соединений.

score(server) = activeConnections(server) / weight(server)
next request -> argmin(score) over all healthy servers

Випадковий та вибори степенів двійки

Чистий випадковий маршрутизація є досить близькою до кругового розподілу в довгостроковій перспективі (за законом великих чисел кожен сервер отримує приблизно 1/N трафіку), але має гіршу короткочасну варіацію — нічого не завадить п’ятьом запитам поспіль припадати на один і той же сервер. Цікаве вдосконалення – вибори степенів двійки: замість випадкового вибору одного сервера, балансер випадково відбирає два сервери та надсилає запит до того, хто з двох має менше активних з’єднань. Аналіз Майкла Мітценмахер показав, що це просте коригування зменшує максимальне навантаження на будь-який сервер з O(log n / log log n) (чистий випадковий) до O(log log n) – експоненційний покращення – за незначний приріст в обробці даних, тому це зустрічається всередині реальних систем, таких як розширення least_conn у nginx та багато сервісних мереж.

Що насправді роблять черги щодо затримки

Кожна з вищезазначених політик намагається досягти одного й того ж цілі: тримати чергу кожного сервера короткою та приблизно рівномірною. Закон Ліві, L = λW, пов’язує довжину черги L із швидкістю приходу запитів λ та середнім часом перебування в системі W — для заданої швидкості приходу запитів єдиним способом зменшити час очікування є зменшення довжини черги, а єдиним способом зменшити довжину черги без втрати запитів є маршрутизація роботи там, де черга насправді коротша. Це і пояснює, чому переважно використовують алгоритми з найменшою кількістю з’єднань та з використанням чисел степенів двох, а не випадкову чергування під час пікового навантаження або при неоднорідному розподілі навантажень: вони використовують інформацію про довжину черги в реальному часі, яку випадкове чергування ігнорує.

// naive least-connections routing
function route(servers) {
  let best = null;
  for (const srv of servers) {
    if (!srv.healthy) continue;
    if (!best || srv.active / srv.weight < best.active / best.weight) best = srv;
  }
  best.active++;
  return best;
}

Перевірки стану здоров’я, «прилипанність» та відмовостійкість

Жодно з цього не має значення, якщо балансер продовжує надсилати трафік до непрацюючого сервера. Перевірки стану здоров’я – періодичні пінг-сигнали або синтетичні запити – виключають несправні бэкенди з обігу та повертають їх у роботу, коли вони відновлюються, зазвичай із повільного старту, щоб нещодавно відновився сервер не отримував миттєво повної частки трафіку, поки його кеші холодні. «Прилипанність» сесії (маршрутизація певного клієнта послідовно до одного бэкенду, часто за допомогою cookie або консистентного хешування на IP-адресі клієнта) обмінює якість балансування навантаження на простоту, коли бэкенди зберігають локальні дані сесій; консистентне хешування особливо зменшує кількість клієнтів, які перемальовуються при додаванні або видаленні сервера, що має велике значення для швидкості попадання в кеш.

Frequently asked questions

Яка політика балансування навантаження найшвидша?

Немає універсального переможця. Round robin та random є найдешевшими в обчисленнях, але ігнорують динамічне навантаження. Least connections та power-of-two-choices коштують трохи більше обробки, але значно краще справляються з нерівномірними тривалістю запитів, що зазвичай має більшого значення для реальної затримки кінцевого трафіку, ніж власні витрати процесора балансера.

Що таке power of two choices і чому це працює так добре?

Замість вибору єдиного найкращого сервера (дорого коштує відстежувати глобально) або повністю випадкового (нерівномірно розподіляє навантаження), балансер зразок двох випадкових серверів і обирає менш завантажений. Цей простий трюк доводиться експоненціально коротшим найгіршими випадками черги, ніж чисто випадкове маршрутизація, при цьому вартість значно нижча, ніж точне відстеження кожного сервера.

Чому повільно запускаються сервери потребують особливого ставлення?

Сервер, який нещодавно знову увійшов до пулу після перезапуску, має холодні кеші та порожні пули з’єднань, тому спочатку він повільніший на запит. Якщо балансер одразу надсилає йому повний обсяг трафіку, він може бути перевантажений і вимкнений знову. Slow start поступово збільшує його частку трафіку.

Спробуйте наживо

Усе, що вище, працює прямо у вашому браузері — відкрийте Load Balancer і змінюйте параметри під час роботи. Нічого не встановлюється, нічого не завантажується на сервер, уся модель живе в одній вкладці.

▶ Відкрити симуляцію Load Balancer

Що ви знайшли?

Додати кроки відтворення (опційно)