Load Balancers

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

Why? #

Когда комьютер (читай приложение) существует в единственном экземпляре всё просто. Каждый запрос будет обработан именно этим самым инстансом.

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

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

Это, кстати, не обязательно так. Можно распределять запросы по различным серверам на уровне DNS. Пример как это работает в Amazon Route 53.

Во-вторых, балансеры не просто распределяют запросы, они балансируют нагрузку.

Нагрузка это что? Это хороший вопрос. В зависимости от конкретного профиля нагрузки есть разные алгоритмы. Рассмотрим некоторые из них.

Strategies #

Во-первых, стоит убедиться, что сервер вообще жив, прежде чем давать на него нагрузку. Для этого, обычно, делают специальный endpoint healthcheck, который просто отвечает 200 и ничего не делает.

Балансер держит пул доступных серверов, периодически опрашивает healthcheck и убирает из пула нерабочий сервер. Точнее переносит в другой пул, чтобы проверить потом и вернуть снова в рабочий, если сервер ожил.

Итак, какие же есть стратегии.

Least Connection Method #

Балансер держит очередь с приоритетом, сортируя сервера по количеству активных соединений. Первым в очереди держим сервер с минимальным количеством соединений.

Когда выгодно? Когда много активных соединений. Скажем делаем стриминг или чат.

Least Response Time Method #

Улучаем предыдущий способ. Кроме количества активных соединений так же учитываем среднее время ответа. Зачем? Соединения неравнозначны, т.е. в зависимости от того, что там на серверах обрабатывается загружены они по-разному.

Round Robin Method #

Самый простой алгоритм. Балансер держит обычную очередь, берёт первый доступный сервер из пула, роутит трафик туда, кладёт этот сервер в конец очереди. Таким образом сервера равномерно нагружены.

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

IP Hash #

Используем некоторый алгоритм шардирования по IP-адресам (клиента и сервера), который имеет смысл в нашем конкретном случае. Может быть удобно, например, если после реконнекта важно попасть на ту же самую машинку.

How? #

Я несколько раз упомянул «очередь», так что кажется, что балансер — исключительно софт. Я и сам так думал, однако есть и хардверные решения, например, Citrix NetScaler. Если хочется получить максимальную производительность и денег вагон.

В реальности, конечно, используется и то и то. Скажем, хардверные балансеры роутят вообще весь трафик во внутреннюю сеть, а дальше уже работают выделенные сервера с софтом. Их можно ставить между любыми компонентами системы: инстансами приложения, кешами а-ля Redis, инстансами базы и т.д., при необходимости.

Конкретный пример софтверного решения — HAProxy.

Резервируем порты под различные пулы, например, 9000 это приложение, 9001 база на запись, 9002 база на чтение. Настраиваем HAProxy так, что весь трафик с определённых портов идёт в соответствующие пулы инстансов. Для каждого пула можно выбрать свою стратегию.

Redundancy #

Разве балансер не будет критическим узлом системы, раз он роутит весь трафик? Так и есть. Поэтому и сам балансер представляет собой пул серверов: отказывает один, на помощь приходит другой.

Вообще, это нормальная история в распределённых системах — на всякий случай надо иметь всего как минимум по два 😃

Материалы #

PS. Обсудить можно в телеграм-чате любознательных программистов. Welcome! 🤗

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