Введение
Балансировка нагрузки — основа современной доставки приложений. Когда тысячи или миллионы пользователей одновременно обращаются к вашему приложению, один сервер не может справиться с нагрузкой. Балансировщики нагрузки распределяют входящий трафик между несколькими серверными backend, обеспечивая высокую доступность, оптимальную производительность и отказоустойчивость.
Но как балансировщик нагрузки решает, какой сервер должен обрабатывать каждый запрос? Ответ кроется в алгоритмах балансировки нагрузки. Выбор правильного алгоритма может означать разницу между отзывчивым приложением и тем, что страдает от тайм-аутов и неравномерной нагрузки на серверы.
Это руководство рассматривает алгоритмы балансировки нагрузки в двух категориях: алгоритмы распределения, определяющие, как трафик распространяется по серверам, и методы persistence, обеспечивающие непрерывность сессии для stateful-приложений.
Почему выбор алгоритма важен
Правильный алгоритм балансировки нагрузки напрямую влияет на производительность приложения, пользовательский опыт и эффективность инфраструктуры:
Улучшение времени отклика при оптимальном выборе алгоритма vs базовый round robin
Исследование производительности NGINXКорпоративное требование к доступности — лишь 52 минуты простоя в год
Отраслевой стандарт SLAПользователи уходят, если страница загружается дольше 3 секунд
Исследование производительности веб GoogleРост ёмкости при интеллектуальном распределении vs один сервер
Лучшие практики балансировки нагрузкиКатегории алгоритмов
Алгоритмы балансировки нагрузки делятся на две основные категории, каждая из которых служит разным архитектурным потребностям:
Алгоритмы распределения
Определяют, как трафик распространяется по серверам — последовательно, случайно или на основе метрик сервера в реальном времени, таких как соединения или время отклика.
Методы persistence
Обеспечивают непрерывность сессии, последовательно направляя запросы от одного клиента, URI или ID пользователя на один и тот же сервер.
На основе производительности
Продвинутые алгоритмы, учитывающие метрики состояния сервера — время отклика, глубина очереди, ошибки соединений — для оптимальных решений маршрутизации.
Гибридные подходы
Сочетают распределение с persistence или используют выбор по нескольким критериям (например, Fastest+) для изощрённых сценариев балансировки нагрузки.
Алгоритмы распределения
Алгоритмы распределения сосредоточены на распространении трафика по пулу серверов. Выбор зависит от инфраструктуры серверов, характеристик запросов и требований к производительности.
Round Robin
Round Robin — простейший и наиболее широко развёрнутый алгоритм балансировки нагрузки. Работает точно так, как следует из названия: запросы распределяются по серверам в круговом, последовательном порядке. Первый запрос идёт на сервер 1, второй — на сервер 2, и так далее. После достижения последнего сервера цикл начинается заново.
Этот алгоритм предполагает, что все серверы имеют равную ёмкость и все запросы требуют сравнимой мощности обработки. Он не требует отслеживания состояния, кроме знания о том, какой сервер следующий в ротации, что делает его чрезвычайно эффективным с минимальными вычислительными накладными расходами.
Round Robin отлично подходит для однородных сред, где серверы имеют идентичные спецификации, а запросы относительно однородны — например, для обслуживания статического контента, простых API-эндпоинтов или stateless-микросервисов.
Round Robin: краткий обзор
| Аспект | Подробности |
|---|---|
| Как работает | Последовательное распределение: сервер 1 → сервер 2 → сервер 3 → повтор |
| Лучше всего для | Однородные серверы, равномерные нагрузки, stateless-приложения |
| Сильные стороны | Простой, предсказуемый, нулевые вычислительные расходы, лёгкая отладка |
| Слабости | Игнорирует нагрузку сервера и различия в ёмкости |
| Сценарии использования | Статический контент, edge-узлы CDN, stateless API |
Weighted Round Robin
Weighted Round Robin расширяет базовый алгоритм, присваивая вес каждому серверу на основе его ёмкости. Серверы с более высокими весами получают пропорционально больше трафика. Если у сервера A вес 3, а у сервера B вес 1, сервер A обрабатывает три запроса на каждый один, обрабатываемый сервером B.
Этот алгоритм необходим для неоднородных серверных сред. Организации часто используют смесь оборудования — мощные новые серверы рядом со старыми машинами или облачные инстансы с разным количеством vCPU. Weighted Round Robin гарантирует, что 16-ядерный сервер обрабатывает больше трафика, чем 4-ядерный.
Веса обычно конфигурируются на основе ядер CPU, памяти или тестирования бенчмарками. Хотя этот алгоритм более гибкий, чем простой Round Robin, он всё же не учитывает нагрузку сервера в реальном времени — сильно взвешенный сервер под высокой нагрузкой будет продолжать получать трафик в зависимости от своего веса, а не текущей ёмкости.
Начните с весов, пропорциональных ядрам CPU или памяти. Например, если у сервера A 8 ядер, а у сервера B 4 ядра, присвойте веса 8 и 4 (или 2 и 1). Мониторьте и корректируйте на основе реальных метрик производительности — пропускной способности, времени отклика и частоты ошибок.
Least Connection
Least Connection использует динамический подход: каждый новый запрос идёт на сервер с наименьшим количеством активных соединений в этот момент. В отличие от Round Robin, этот алгоритм адаптируется к условиям в реальном времени — если один сервер обрабатывает много медленных запросов, новые запросы маршрутизируются на менее загруженные серверы.
Этот алгоритм особенно рекомендуется для серверов, обрабатывающих длительные сессии. Соединения с базами данных (SQL), сервисы каталогов (LDAP) и приложения с персистентными соединениями значительно выигрывают от распределения Least Connection.
Балансировщик нагрузки отслеживает активные соединения с каждым серверным backend. При поступлении нового запроса он запрашивает эту таблицу соединений и выбирает сервер с наименьшим счётом. Эти небольшие накладные расходы пренебрежимо малы по сравнению с преимуществами производительности для нагрузок с большим числом соединений.
Least Connection: краткий обзор
| Аспект | Подробности |
|---|---|
| Как работает | Маршрутизирует на сервер с наименьшим количеством активных соединений |
| Лучше всего для | Длительные сессии, персистентные соединения, нагрузки баз данных |
| Сильные стороны | Адаптируется к нагрузке в реальном времени, предотвращает перегрузку сервера, изящно обрабатывает медленные запросы |
| Слабости | Небольшие накладные расходы на отслеживание соединений |
| Сценарии использования | SQL-базы данных, LDAP-каталоги, WebSocket-приложения, API с длительно выполняющимися запросами |
First
Алгоритм First использует уникальный подход: он отправляет весь трафик на первый сервер в пуле, пока этот сервер не достигнет своего максимального лимита соединений. Только тогда трафик идёт на следующий сервер.
Этот алгоритм полезен для конфигураций active-passive, где вы хотите, чтобы один основной сервер обрабатывал всю нагрузку, в то время как другие остаются в резерве. Он также ценен для лицензионных сценариев, где вы хотите максимально использовать один лицензированный сервер до задействования дополнительной ёмкости.
First обеспечивает предсказуемое поведение и упрощает устранение неполадок, поскольку вы знаете точно, какой сервер обрабатывает трафик. Однако он не обеспечивает преимуществ распределения нагрузки и полностью полагается на лимиты max connection для failover.
First: краткий обзор
| Аспект | Подробности |
|---|---|
| Как работает | Первый сервер получает всю нагрузку, пока не будет достигнут max connections |
| Лучше всего для | Active-passive-конфигурации, оптимизация лицензий, предсказуемая маршрутизация |
| Сильные стороны | Простой, предсказуемый, максимизирует использование одного сервера |
| Слабости | Нет распределения нагрузки, зависит от конфигурации max connection |
| Сценарии использования | Конфигурации основной-резервный, лицензированное ПО, сценарии переполнения ёмкости |
Random
Алгоритм Random выбирает серверы случайно для каждого входящего запроса. Однако, в отличие от чистой рандомизации, эта реализация учитывает как веса серверов, так и время отклика в своей вероятности выбора.
Этот взвешенный случайный подход обеспечивает статистическое распределение нагрузки, избегая предсказуемых шаблонов Round Robin. Со временем серверы получают трафик пропорционально своим весам, но случайный элемент предотвращает синхронизированные шаблоны запросов, которые могут вызывать периодические всплески нагрузки.
Случайный выбор особенно эффективен в больших пулах серверов, где закон больших чисел обеспечивает равномерное распределение. Он также полезен, когда вы хотите избежать проблемы «thundering herd», когда несколько клиентов одновременно нацеливаются на один и тот же сервер.
Random: краткий обзор
| Аспект | Подробности |
|---|---|
| Как работает | Случайный выбор сервера с учётом веса и времени отклика |
| Лучше всего для | Больших пулов серверов, избегания синхронизированных шаблонов |
| Сильные стороны | Предотвращает thundering herd, статистически равномерное распределение, учитывает производительность |
| Слабости | Менее предсказуемый, чем Round Robin, может иметь краткосрочные дисбалансы |
| Сценарии использования | Высоконагруженные приложения, большие кластеры, кэш-серверы |
Fastest
Алгоритм Fastest маршрутизирует запросы на сервер с лучшим временем отклика. Балансировщик нагрузки непрерывно мониторит производительность сервера и направляет трафик на тот сервер, который в данный момент отвечает быстрее всего.
Этот подход оптимизирует пользовательский опыт, гарантируя, что запросы идут на самый отзывчивый сервер. Он автоматически адаптируется к изменяющимся условиям — если сервер становится медленным из-за высокого CPU, нагрузки на память или внешних зависимостей, трафик смещается на более быстрые альтернативы.
Fastest идеален для приложений, чувствительных к задержке, где время отклика напрямую влияет на пользовательский опыт или бизнес-метрики. Потоки оформления заказа e-commerce, API реального времени и интерактивные приложения — все выигрывают от маршрутизации на основе времени отклика.
Fastest+
Fastest+ — самый изощрённый алгоритм, предлагающий двухуровневую оптимизацию с настраиваемыми критериями. Вы выбираете основную метрику (Opt-1) для выбора сервера и вторичную метрику (Opt-2), которая разрешает ничьи, когда у нескольких серверов равные основные значения.
Доступные критерии оптимизации включают: Least Response Time, Least Connection Time, Least Queue Time, Least Queues, Least Connection Error, Least Aborted Connections и Least Used Connections. Эта гибкость позволяет тонко настроить оптимизацию для характеристик вашей конкретной нагрузки.
Например, вы можете сконфигурировать Opt-1 как «Least Response Time» и Opt-2 как «Least Connection Error». Алгоритм сначала выбирает серверы с лучшим временем отклика, затем среди них выбирает тот, у которого наименьшее количество ошибок соединений. Этот многокритериальный подход справляется со сложными production-сценариями, где одиночных метрик недостаточно.
Опции оптимизации Fastest+
| Опция | Описание | Лучше всего для |
|---|---|---|
| Least Response Time | Сервер, отвечающий на запросы быстрее всего | Приложения, чувствительные к задержке |
| Least Connection Time | Сервер, устанавливающий соединения быстрее всего | Нагрузки с высокой текучкой соединений |
| Least Queue Time | Сервер с кратчайшим ожиданием очереди запросов | Всплесковые шаблоны трафика |
| Least Queues | Сервер с наименьшим количеством запросов в очереди | Избегание накопления запросов |
| Least Connection Error | Сервер с наименьшим количеством неуспешных соединений | Критически надёжные приложения |
| Least Aborted Connections | Сервер с наименьшим количеством отключений клиентов | Нагрузки с длительно выполняющимися запросами |
| Least Used Connections | Сервер с наименьшим использованием соединений | Приложения с пулом соединений |
Fastest+ использует вторичный критерий (Opt-2) только когда несколько серверов имеют ничью по основному критерию (Opt-1). Это обеспечивает оптимальный выбор даже в однородных средах, где у серверов часто схожие характеристики производительности.
Методы persistence (самоперсистентные)
Методы persistence гарантируют, что связанные запросы от одного клиента, сессии или контекста всегда достигают одного и того же серверного backend. Это необходимо для stateful-приложений, хранящих данные сессии локально, а не в общем хранилище.
Source (IP persistence)
Source persistence использует хеш исходного IP-адреса клиента для выбора сервера. Значение хеша сочетается с весами серверов для определения маршрутизации. Один и тот же IP клиента всегда производит один и тот же хеш, обеспечивая согласованную маршрутизацию на один и тот же сервер.
Этот метод обеспечивает persistence сессии без необходимости в cookie или изменениях на уровне приложения. Все запросы с конкретного IP-адреса идут на один и тот же сервер, поддерживая любое состояние сессии, хранящееся на этом сервере.
У Source persistence есть ограничения в средах NAT, где несколько пользователей делят один IP-адрес, и с мобильными пользователями, которые могут менять IP-адреса. Для этих сценариев методы persistence на уровне приложения (URI, URL Param, HDR) обеспечивают лучшие результаты.
URI (persistence по пути)
URI persistence хеширует путь URI запроса для определения маршрутизации сервера. Текст URI до указанной длины (или до символа '?', если присутствуют query-параметры) хешируется и сочетается с весами серверов. Одни и те же URI всегда маршрутизируются на один и тот же сервер.
Опции конфигурации включают длину символов URI и глубину URI (количество сегментов пути для рассмотрения). Например, при глубине 2 и «/api/users/123», и «/api/users/456» будут хешировать тот же префикс «/api/users».
Этот метод отлично подходит для сценариев кэширования, где вы хотите, чтобы все запросы на один и тот же ресурс попадали на один и тот же сервер, максимизируя эффективность кэша. Он также полезен для шардированных backend, где разные шаблоны URI соответствуют разным партициям данных.
URL Param (persistence параметра)
URL Param persistence извлекает указанный параметр из URL (или тела POST) и использует его значение для маршрутизации сервера. Это обычно используется для отслеживания ID пользователей, сессионных токенов или других идентификаторов, специфичных для приложения. Одни и те же значения параметра всегда маршрутизируются на один и тот же сервер.
Вы конфигурируете имя URL-параметра для извлечения и опционально включаете проверку POST-параметра для отправки форм. Это обеспечивает persistence с учётом приложения, следующий за пользовательскими сессиями независимо от изменений IP-адреса.
Этот метод идеален для приложений, встраивающих идентификаторы сессии или пользователя в URL или данные форм. Он обеспечивает более надёжную persistence, чем методы на основе IP, для мобильных пользователей или находящихся за NAT.
HDR (persistence заголовка)
HDR persistence исследует указанный HTTP-заголовок в каждом запросе и маршрутизирует на основе его содержимого. Запросы с одинаковым значением заголовка всегда идут на один и тот же сервер. Вы конфигурируете, какое имя заголовка инспектировать.
Распространённые сценарии использования включают маршрутизацию на основе кастомных сессионных заголовков, API-ключей, идентификаторов арендатора в многотенантных приложениях или JWT-токенов. Это обеспечивает максимальную гибкость для приложений, управляющих собственными идентификаторами сессии.
HDR persistence особенно ценна для API-first архитектур и микросервисов, где состояние сессии управляется через заголовки, а не cookie. Она плавно интегрируется с системами аутентификации на основе токенов.
Hash (продвинутая кастомная persistence)
Hash persistence — самый мощный и гибкий метод, позволяющий строить кастомные ключи persistence практически из любого элемента в потоке трафика. Балансировщик нагрузки поддерживает хеш-таблицу (до 3 миллионов записей по умолчанию), сопоставляющую кастомные значения ключей с серверными backend, с настраиваемым истечением (по умолчанию 7 дней).
Ключ хеша может быть построен из сотен доступных переменных: IP и порт клиента, временные метки, поля SSL-сертификата, информация frontend, путь URL и метод, HTTP-заголовки, содержимое тела запроса, результаты обработки WAAP и многое другое. Вы можете комбинировать несколько переменных и применять функции трансформации для создания точно той логики persistence, которая требуется вашему приложению.
Например, вы могли бы создать ключ хеша, который: извлекает страну из IP клиента, проверяет, находится ли она в конкретном списке, затем сочетает это с именем пользователя из SSL-сертификата клиента. Все запросы, производящие одинаковое значение хеша из этой комбинации — что означает пользователей из одного региона с той же сертификатной идентичностью, — всегда будут направляться на один и тот же серверный backend. Это обеспечивает чрезвычайно гранулярный контроль persistence при поддержании состояния сессии приложения. Этот уровень настройки позволяет сценарии persistence, которых другие балансировщики нагрузки просто не могут достичь, делая его одной из отличительных возможностей TR7.
Строительные блоки ключа хеша
Ключ хеша может быть построен из любой комбинации этих элементов трафика:
| Категория | Доступные переменные | Пример использования |
|---|---|---|
| Уровень сети | IP клиента, порт клиента, IP сервера, порт сервера | Гео-маршрутизация, привязка к сегменту сети |
| SSL/TLS | CN сертификата, DN сертификата, SNI, шифр-сюита | Маршрутизация на основе сертификата клиента, сценарии mTLS |
| HTTP-запрос | Метод, путь, URL, query-параметры, заголовок Host | Маршрутизация на основе контента, версионирование API |
| HTTP-заголовки | Любое значение заголовка (Authorization, X-Tenant-ID и т. д.) | Многотенантная маршрутизация, привязка к API-ключу |
| Тело запроса | POST-параметры, поля JSON, данные форм | Persistence на основе транзакций |
| Контекст | Время, дата, имя frontend, решение WAAP, страна GeoIP | Маршрутизация на основе времени, маршрутизация соответствия |
Ключи хеша поддерживают функции трансформации: манипуляция строками (substring, regex), кодирование (base64, URL encode), поиск (страна GeoIP, ASN) и условную логику. Сочетайте их для построения сложных правил persistence. Например: «Если клиент из стран ЕС И имеет валидный клиентский сертификат, постройте ключ хеша из CN сертификата; иначе постройте из заголовка Authorization» — гарантируя, что запросы, соответствующие одним условиям, всегда достигают одного и того же серверного backend.
Сравнение методов persistence
| Метод | На основе | Конфигурация | Лучше всего для |
|---|---|---|---|
| Source | Хеш IP-адреса клиента | Нет (автоматически) | Простые веб-приложения, унаследованные системы |
| URI | Хеш пути запроса | Длина URI, глубина URI | Кэширование, маршрутизация контента, шардированные backend |
| URL Param | Значение URL/POST-параметра | Имя параметра, опция проверки POST | Отслеживание сессии, маршрутизация по пользователю |
| HDR | Значение HTTP-заголовка | Имя заголовка | API-аутентификация, многотенантные приложения, JWT-маршрутизация |
| New Cookie | Cookie, управляемый LB | Имя cookie, max-idle, max-life | Без изменений приложения, контроль тайм-аута сессии |
| Current Cookie | Существующий cookie приложения | Имя cookie для отслеживания | Использование существующих сессий приложения |
| Hash | Выражение кастомного ключа | Переменные ключа, функции, 3 млн записей, TTL 7 дней | Сложная многофакторная persistence, максимальная гибкость |
Руководство по выбору алгоритма
Выбор правильного алгоритма зависит от ваших конкретных требований. Это сравнение подчёркивает ключевые компромиссы:
| Алгоритм | Учёт нагрузки | Сложность | Persistence | Основной сценарий использования |
|---|---|---|---|---|
| Round Robin | Нет | Минимальная | Нет | Однородные stateless-нагрузки |
| Weighted Round Robin | Статический (веса) | Низкая | Нет | Смешанные ёмкости серверов |
| Least Connection | Динамический (соединения) | Средняя | Нет | Длительные сессии, базы данных |
| First | Нет | Минимальная | Нет | Active-passive, оптимизация лицензий |
| Random | Динамический (время отклика) | Низкая | Нет | Большие кластеры, кэш-серверы |
| Fastest | Динамический (время отклика) | Средняя | Нет | Приложения, чувствительные к задержке |
| Fastest+ | Мультикритериальный | Высокая | Нет | Сложные production-среды |
| Source | Через веса | Низкая | Да (IP) | Простая persistence сессии |
| URI | Через веса | Средняя | Да (путь) | Кэширование, маршрутизация контента |
| URL Param | Через веса | Средняя | Да (ID пользователя) | Отслеживание сессии пользователя |
| HDR | Через веса | Средняя | Да (заголовок) | Маршрутизация API, многотенантные |
Выбор алгоритма
Используйте алгоритмы распределения, когда
- Приложение stateless или использует общее хранилище сессий
- Нужно распределить нагрузку по пулу серверов
- У серверов разные ёмкости (используйте Weighted)
- Оптимизация времени отклика критична (используйте Fastest/Fastest+)
Используйте методы persistence, когда
- Приложение хранит данные сессии локально на серверах
- Серверные сервисы шардированы по пользователю или контенту
- Эффективность кэширования требует согласованной маршрутизации
- Используется аутентификация на основе токена или заголовка
Используйте Fastest+, когда
- Одна метрика не охватывает вашу цель оптимизации
- Нужна логика разрешения ничьи для однородных серверов
- Важны и производительность, и надёжность
- Сложная production-среда с разнообразными нагрузками
Лучшие практики реализации
Независимо от выбранного алгоритма, эти практики обеспечивают оптимальную производительность балансировки нагрузки:
Внедрите надёжные проверки состояния
Сконфигурируйте активные проверки состояния, верифицирующие функциональность приложения, а не только TCP-связность. Сервер, отвечающий на пинги, но возвращающий ошибки 500, должен быть удалён из ротации.
Мониторьте и корректируйте веса
Для взвешенных алгоритмов пересматривайте назначения весов ежеквартально или после изменений инфраструктуры. Тестируйте серверы под реалистичной нагрузкой для определения точных соотношений ёмкости.
Выбирайте persistence мудро
Проектируйте приложения stateless, когда возможно, храня сессии во внешних хранилищах, таких как Redis. Если persistence требуется, выбирайте метод, лучше всего соответствующий вашему идентификатору сессии (IP, URI, параметр или заголовок).
Тестируйте сценарии failover
Регулярно тестируйте сбои серверов для обеспечения изящного failover. Верифицируйте, что поведение алгоритма корректно, когда серверы удаляются и заново добавляются в пул.
Используйте Fastest+ для сложных сценариев
Когда одноментрические алгоритмы не удовлетворяют ваши потребности, сконфигурируйте Fastest+ с основным и вторичным критериями. Начните с Least Response Time как Opt-1 и Least Connection Error как Opt-2.
Часто задаваемые вопросы
Да, методы persistence (Source, URI, URL Param, HDR) уже включают веса серверов в свои решения маршрутизации. Это означает, что вы получаете и привязку сессии, и распределение с учётом ёмкости. Выбор на основе хеша взвешивается согласно конфигурациям серверов.
Используйте Fastest, когда время отклика — ваша единственная забота, а серверы имеют явно разные характеристики производительности. Используйте Fastest+, когда нужен более нюансированный выбор — например, оптимизация по времени отклика, но предпочтение серверов с меньшим количеством ошибок, когда времена отклика схожи.
Когда персистентный сервер становится недоступным, запросы перенаправляются на другой сервер на основе перераспределения хеша алгоритма persistence. Данные сессии на упавшем сервере теряются, если ваше приложение не использует внешнее хранилище сессий. Проверки состояния гарантируют быстрое удаление упавших серверов из пула.
Least Connection как отдельный алгоритм маршрутизирует на сервер с наименьшим количеством активных соединений. «Least Used Connections» в Fastest+ учитывает использование соединений относительно ёмкости сервера, делая его более подходящим для неоднородных серверных сред.
Для мобильных приложений избегайте Source (IP) persistence, поскольку мобильные устройства часто меняют IP-адреса. Используйте URL Param persistence с ID пользователя или сессионным токеном или HDR persistence с заголовком аутентификации. Эти методы следуют за сессией пользователя независимо от изменений сети.
Заключение
Алгоритмы балансировки нагрузки фундаментальны для доставки приложений, однако часто упускаются из виду во время архитектурных решений. Правильный алгоритм обеспечивает равномерное использование серверов, оптимальное время отклика и устойчивый failover, в то время как неправильный выбор может создавать горячие точки, деградировать производительность и усложнять устранение неполадок.
Для большинства production-сред начните с Least Connection для динамических нагрузок или Weighted Round Robin для статического распределения ёмкости. По мере созревания ваших возможностей мониторинга исследуйте Fastest+ для многокритериальной оптимизации. Выбирайте методы persistence на основе вашей стратегии управления сессиями — Source для простоты или URI/URL Param/HDR для маршрутизации с учётом приложения.
Интеллектуальное распределение трафика
Балансировщик нагрузки TR7 поддерживает все основные алгоритмы, включая продвинутый Fastest+ с многокритериальной оптимизацией, плюс гибкие опции persistence для маршрутизации с учётом сессий. Оптимизируйте доставку приложений с балансировкой нагрузки корпоративного класса.
Изучить ADC