Балансировка на сетевом уровне. Балансировка на прикладном уровне

Вопрос о планировании нагрузки следует решать ещё на ранней стадии развития любого веб-проекта. «Падение» сервера (а оно всегда происходит неожиданно, в самый неподходящий момент) чревато весьма серьёзными последствиями — как моральными, так и материальными. Первоначально проблемы недостаточной производительности сервера в связи ростом нагрузок можно решать путем наращивания мощности сервера, или же оптимизацией используемых алгоритмов, программных кодов и так далее. Но рано или поздно наступает момент, когда и эти меры оказываются недостаточными.

Приходится прибегать к кластеризации: несколько серверов объединяются в кластер; нагрузка между ними распределяется при помощи комплекса специальных методов, называемых балансировкой. Помимо решения проблемы высоких нагрузок кластеризация помогает также обеспечить резервирование серверов друг на друга.
Эффективность кластеризации напрямую зависит от того, как распределяется (балансируется) нагрузка между элементами кластера.

Балансировка нагрузки может осуществляться при помощи как аппаратных, так и программных инструментов. Об основных методах и алгоритмах и балансировки мы бы хотели рассказать в этой статье.

Уровни балансировки

Процедура балансировки осуществляется при помощи целого комплекса алгоритмов и методов, соответствующим следующим уровням модели OSI:
  • сетевому;
  • транспортному;
  • прикладному.

Рассмотрим эти уровни более подробно.

Балансировка на сетевом уровне

Балансировка на сетевом уровне предполагает решение следующей задачи: нужно сделать так, чтобы за один конкретный IP-адрес сервера отвечали разные физические машины. Такая балансировка может осуществляться с помощью множества разнообразных способов.

Балансировка на транспортном уровне

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

Иногда балансировку на транспортном уровне сложно отличить от балансировки на сетевом уровне. Рассмотрим следующее правило для сетевого фильтра pf в BSD-системах: так, например, формально тут идет речь про балансировку трафика на конкретном порту TCP (пример для сетевого фильтра pf в BSD-системах):

Web_servers = "{ 10.0.0.10, 10.0.0.11, 10.0.0.13 }" match in on $ext_if proto tcp to port 80 rdr-to $web_servers round-robin sticky-address

Речь в нём идет о балансировке трафика на конкретном порту TCP.

Рассмотрим теперь другой пример:

Pass in on $int_if from $lan_net \ route-to { ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) }\ round-robin

В этом правиле речь о балансировке исходящего трафика на сетевом уровне. В нём не указано ни конкретного порта, ни конкретного протокола.

Различие между уровнями балансировки можно объяснить следующим образом. К сетевому уровню относятся решения, которые не терминируют на себе пользовательские сессии. Они просто перенаправляют трафик и не работают в проксирующем режиме.
На сетевом уровне балансировщик просто решает, на какой сервер передавать пакеты. Сессию с клиентом осуществляет сервер.

На транспортном уровене общение с клиентом замыкается на балансировщике, который работает как прокси. Он взаимодействует с серверами от своего имени, передавая информацию о клиенте в дополнительных данных и заголовках. Таким образом работает, например, популярный программный балансировщик HAProxy.

Балансировка на прикладном уровне

При балансировке на прикладном уровне балансировщик работает в режиме «умного прокси». Он анализирует клиентские запросы и перенаправляет их на разные серверы в зависимости от характера запрашиваемого контента. Так работает, например, веб-сервер Nginx, распределяя запросы между фронтендом и бэкендом. За балансировку в Nginx отвечает модуль Upstream. Более подробно об особенностях балансировки Nginx на основе различных алгоритмов можно прочитать, например, .

В качестве ещё одного примера инструмента балансировки на прикладном уровне можно привести pgpool — промежуточный слой между клиентом и сервером СУБД PostgreSQL. С его помощью можно распределять запросы оп серверам баз данных в зависимости от их содержания,: например, запросы на чтение будут передаваться на один сервер, а запросы на запись — на другой. Подробнее о pgpool и специфике работы с ним можно почитать в этой статье).

Алгоритмы и методы балансировки

Существует много различных алгоритмов и методов балансировки нагрузки. Выбирая конкретный алгоритм, нужно исходить, во-первых, из специфики конкретного проекта, а во-вторых — из целей. которые мы планируем достичь.

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

  • справедливость : нужно гарантировать, чтобы на обработку каждого запроса выделялись системные ресурсы и не допустить возникновения ситуаций, когда один запрос обрабатывается, а все остальные ждут своей очереди;
  • эффективность : все серверы, которые обрабатывают запросы, должны быть заняты на 100%; желательно не допускать ситуации, когда один из серверов простаивает в ожидании запросов на обработку (сразу же оговоримся, что в реальной практике эта цель достигается далеко не всегда);
  • сокращение времени выполнения запроса : нужно обеспечить минимальное время между началом обработки запроса (или его постановкой в очередь на обработку) и его завершения;
  • сокращение времени отклика : нужно минимизировать время ответа на запрос пользователя.

Очень желательно также, чтобы алгоритм балансировки обладал следующими свойствами:

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

Round Robin

Round Robin, или алгоритм кругового обслуживания, представляет собой перебор по круговому циклу: первый запрос передаётся одному серверу, затем следующий запрос передаётся другому и так до достижения последнего сервера, а затем всё начинается сначала.

Самой распространёной имплементацией этого алгоритма является, конечно же, метод балансировки Round Robin DNS. Как известно, любой DNS-сервер хранит пару «имя хоста — IP-адрес» для каждой машины в определённом домене. Этот список может выглядеть, например, так:

Example.com xxx.xxx.xxx.2 www.example.com xxx.xxx.xxx.3

С каждым именем из списка можно ассоциировать несколько IP-адресов:

Example.com xxx.xxx.xxx.2 www.example.com xxx.xxx.xxx.3 www.example.com xxx.xxx.xxx.4 www.example.com xxx.xxx.xxx.5 www.example.com xxx.xxx.xxx.6

DNS-сервер проходит по всем записям таблицы и отдаёт на каждый новый запрос следующий IP-адрес: например, на первый запрос — xxx.xxx.xxx.2, на второй — ххх.ххх.ххх.3, и так далее. В результате все серверы в кластере получают одинаковое количество запросов.

В числе несомненных плюсов этого алгоритма следует назвать, во-первых, независимость от протокола высокого уровня. Для работы по алгоритму Round Robin используется любой протокол, в котором обращение к серверу идёт по имени.
Балансировка на основе алгоритма Round Robin никак не зависит от нагрузки на сервер: кэширующие DNS-серверы помогут справиться с любым наплывом клиентов.

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

Алгоритм Round Robin имеет и целый ряд существенных недостатков недостатков. Чтобы распределение нагрузки по этому алгоритму отвечало упомянутым выше критериями справедливости и эффективности, нужно, чтобы у каждого сервера был в наличии одинаковый набор ресурсов. При выполнении всех операций также должно быть задействовано одинаковое количество ресурсов. В реальной практике эти условия в большинстве случаев оказываются невыполнимыми.

Также при балансировке по алгоритму Round Robin совершенно не учитывается загруженность того или иного сервера в составе кластера. Представим себе следующую гипотетическую ситуацию: один из узлов загружен на 100%, в то время как другие — всего на 10 - 15%. Алгоритм Round Robin возможности возникновения такой ситуации не учитывает в принципе, поэтому перегруженный узел все равно будет получать запросы. Ни о какой справедливости, эффективности и предсказуемости в таком случае не может быть и речи.

В силу описанных выше обстоятельств сфера применения алгоритма Round Robin весьма ограничена.

Weighted Round Robin

Это — усовершенствованная версия алгоритма Round Robin. Суть усовершенствований заключается в следующем: каждому серверу присваивается весовой коэффициент в соответствии с его производительностью и мощностью. Это помогает распределять нагрузку более гибко: серверы с большим весом обрабатывают больше запросов. Однако всех проблем с отказоустойчивостью это отнюдь не решает. Более эффективную балансировку обеспечивают другие методы, в которых при планировании и распределении нагрузки учитывается большее количество параметров.

Least Connections

В предыдущем разделе мы перечислили основные недостатки алгоритма Round Robin. Назовём ещё один: в нём совершенно не учитывается количество активных на данный момент подключений.

Рассмотрим практический пример. Имеется два сервера — обозначим их условно как А и Б. К серверу А подключено меньше пользователей, чем к серверу Б. При этом сервер А оказывается более перегруженным. Как это возможно? Ответ достаточно прост: подключения к серверу А поддерживаются в течение более долгого времени по сравнению с подключениями к серверу Б.

Описанную проблему можно решить с помощью алгоритма, известного под названием least connections (сокращённо — leastconn). Он учитывает количество подключений, поддерживаемых серверами в текущий момент времени. Каждый следующий вопрос передаётся серверу с наименьшим количеством активных подключений.

Существует усовершенствованный вариант этого алгоритма, предназначенный в первую очередь для использования в кластерах, состоящих из серверов с разными техническими характеристиками и разной производительностью. Он называется Weighted Least Connections и учитывает при распределении нагрузки не только количество активных подключений, но и весовой коэффициент серверов.

В числе других усовершенствованных вариантов алгоритма Least Connections следует прежде всего выделить Locality-Based Least Connection Scheduling и Locality-Based Least Connection Scheduling with Replication Scheduling.

Первый метод был создан специально для кэширующих прокси-серверов. Его суть заключается в следующем: наибольшее количество запросов передаётся серверам с наименьшим количеством активных подключений. За каждым из клиентских серверов закрепляется группа клиентских IP. Запросы с этих IP направляются на «родной» сервер, если он не загружен полностью. В противном случае запрос будет перенаправлен на другой сервер (он должен быть загружен менее чем наполовину).

В алгоритме Locality-Based Least Connection Scheduling with Replication Scheduling каждый IP-адрес или группа IP-адресов закрепляется не за отдельным сервером, а за целой группой серверов. Запрос передаётся наименее загруженному серверу из группы. Если же все серверы из «родной» группы перегружены, то будет зарезервирован новый сервер. Этот новый сервер будет добавлен к группе, обслуживающей IP, с которого был отправлен запрос. В свою очередь наиболее загруженный сервер из этой группы будет удалён — это позволяет избежать избыточной репликации.

Destination Hash Scheduling и Source Hash Scheduling

Алгоритм Destination Hash Scheduling был создан для работы с кластером кэширующих прокси-серверов, но он часто используется и в других случаях. В этом алгоритме сервер, обрабатывающий запрос, выбирается из статической таблицы по IP-адресу получателя.

Алгоритм Source Hash Scheduling основывается на тех же самых принципах, что и предыдущий, только сервер, который будет обрабатывать запрос, выбирается из таблицы по IP-адресу отправителя.

Sticky Sessions

Sticky Sessions — алгоритм распределения входящих запросов, при котором соединения передаются на один и тот же сервер группы. Он используется, например, в веб-сервере Nginx. Сессии пользователя могут быть закреплены за конкретным сервером с помощью метода IP hash (подробную информацию о нём см. в официальной документации). С помощью этого метода запросы распределяются по серверам на основе IP-aдреса клиента. Как указано в документации (см. ссылку выше), «метод гарантирует, что запросы одного и того же клиента будет передаваться на один и тот же сервер». Если закреплённый за конкретным адресом сервер недоступен, запрос будет перенаправлен на другой сервер. Пример фрагмента конфигурационного файла:

Upstream backend { ip_hash; server backend1.example.com; server backend2.example.com; server backend3.example.com; server backend4.example.com; }

Начиная с версии 1.2.2 в Nginx для каждого сервера можно указывать вес.

Применение этого метода сопряжено с некоторыми проблемами. Проблемы с привязкой сессий могут возникнуть, если клиент использует динамический IP. В ситуации, когда большое количество запросов проходит через один прокси-сервер, балансировку вряд ли можно назвать эффективной и справедливой. Описанные проблемы, однако, можно решить, используя cookies. В коммерческой версии Nginx имеется специальный модуль sticky, который как раз использует cookies для балансировки. Есть у него и бесплатные аналоги — например, nginx-sticky-module .
Можно использовать метод sticky-sessions и в HAProxy — подробнее об этом можно прочитать, например,

Заключение

Эта статья по сути представляет собой введение в проблематику балансировки нагрузки. Обсуждение этой темы мы продолжим и в дальнейших публикациях. Если у вас есть вопросы, замечания и дополнения — добро пожаловать в комментарии. Будем также признательны, если вы поделитесь нетривиальными практическими примерами организации балансировки нагрузки для различных проектов.

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

Теги: Добавить метки

Remote Desktop Connection Broker (RD Connection Broker), ранее известный под именем Terminal Services Session Broker (TS Session Broker), — это роль сервера Windows 2008 R2, предоставляющая следующий функционал:

  • Позволяет пользователям переподключаться к своим текущим сессиям в ферме серверов RD Session Host (терминальные сервера Windows). Тем самым предотвращается создание новых пользовательских подключений на других серверах фермы при наличии подключения в состоянии «disconnected».
  • Позволяет равномерно распределить нагрузку между серверами терминальной фермы RD.

RD Connection Broker отслеживает все сессии пользователей в ферме терминальных серверов Windows Server 2008 R2. База данных RD Connection Broker хранит сессионную информацию, включая имена серверов RD Session Host, на которых находятся сессии пользователя, идентификатор сессии (session ID) и имя пользователя, ассоциированное с сессией. Служба RD Connection Broker использует эту информацию для перенаправления пользователя, уже имеющего активную терминальную сессию на тот сервер, на котором она запущена.

В том случае, если пользователь отключился (disconnect) от своей сессии (из-за сетевого сбоя или осознанно), все приложения, которые он запустил на сервере продолжают работать. И когда пользователь пытается вновь подключиться к ферме терминалов, Connection Broker определяет сервер, на котором уже имеется сессия пользователя и перенаправляет подключение пользователя именно туда.

Балансировка нагрузки RD Connection Broker Load Balancing, позволяет при подключении пользователя (предполагается, что у него не осталось подключений в состоянии disconnect) к ферме, перенаправить его на наименее загруженный сервер фермы (с наименьшим количеством пользовательских сессий). Чтобы более гибко управлять балансировкой нагрузки в ферме терминальных серверов, администратор может в зависимости от вычислительных мощностей серверов фермы назначить каждому из них относительный вес.

Компоненты RD Connection Broker

Для построения фермы терминальных серверов с балансировкой нагрузки нужны два компонента:

Сервер RD Connection Broker . Это сервер с запущенной службой Remote Desktop Connection Broker, который отслеживает сессии пользователей и осуществляет балансировку нагрузки между членами фермы RD. Существует имя сервера RD Connection Broker, с помощью которого можно отнести конкретный терминальный сервер к той или иной ферме.

Сервера RD Session Host , настроенные на использование Connection Broker. Это рядовые члены терминальной фермы. Для того, чтобы являться членом фермы под управление RD Connection Broker, терминальный сервер должен соответствовать следующим критериям:

  • На сервере должна быть установлена роль RD Session Host.
  • Сервер должен быть членом домена Active Directory.
  • Сервер должен входить в локальную группу «Session Broker Computers» на сервере с ролью RD Connection Broker.

Последовательность настройки терминальной фермы RD Connection Broker с балансировкой нагрузки:

  1. Установите роль RD Connection Broker на сервере (это может быть выделенный сервер, или один из членов будущей фермы).
  2. Добавьте все терминальные сервера в локальную группу безопасности «Session Broker Computers» на сервере с ролью RD Connection Broker.
  3. Настройте всех членов фермы на использование сервера RD Connection Broker
  4. Настройте записи DNS для реализация механизма «DNS round robin»

Шаг 1: Установка роли Connection Broker

Если роль Remote Desktop Services уже установлена:

  • Разверните роль Remote Desktop Services.
  • Нажмите кнопку Add Role Services.
  • На странице служб роли выберите Remote Desktop Connection Broker и нажмите Next

В моем стенде 2 сервера, настроенных следующим образом:

RDS01

Шаг 2: Добавляем сервера RD Session Host в локальную группу Session Broker Computers.

Для этого на сервер с установленной ролью RD Connection Broker :

  • Нажмите Start -> Administrative Tools -> Computer Management.
  • В левой панели разверните узел Local Users and Groups, и выберите Groups.
  • Найдите локальную группу Session Broker Computers , и выберите пункт Properties.
  • На вкладке General, нажмите Add.
  • В окне выбора нажмите кнопку Object Types.
  • Отметьте пункт Computers, и нажмите OK.
  • Последовательно укажите и добавьте имена всех серверов, которые будут участвовать в терминальной ферме
  • Нажмите OK.

Шаг 3: Включаем сервера RD Session Host в ферму RD Connection Broker , настраиваем балансировку нагрузки

На каждом из терминальных серверов RD Session Host выполните следующее:

  • На сервер RD Session Host откройте консоль Remote Desktop Session Host Configuration (Start ->Administrative Tools->Remote Desktop Services -> Remote Desktop Session Host Configuration).
  • В разделе Edit settings, щелкните по полю Member of farm in RD Connection Broker.
  • На вкладке RD Connection Broker нажмите кнопку Change Settings.
  • В окне RD Connection Broker Settings выберите Farm member.
  • Введите имя сервера с ролью RD Connection Broker.
  • В окне Farm name, укажите имя создаваемой фермы.
  • Чтобы активировать балансировку нагрузки в ферме RD Connection Broker отметьте опцию Participate in Connection Broker Load-Balancing.
  • В случае необходимости можно настроить относительный вес каждого из серверов в ферме (Server weight). Значение по умолчанию — 100. В том случае, если вы зададите вес одного сервера 100, а другого 50, это будет означать, что сервер с меньшим весом будет получать в 2 раза меньше подключений.
  • По умолчанию используется перенаправление по IP адресу (IP address redirection), также можно использовать перенаправление по токену (Use token redirection).

Я выполнил соответствующую настройку на обоих серверах RDS01 и RDS02


Task 4: Настройка DNS round robin

Для балансировки нагрузки в терминальных фермах RD Session Host, можно использовать балансировку нагрузки RD Connection Broker Load Balancing совместно с функцией DNS round robin. Во втором случае, вы должны для каждого из серверов членов фермы создать DNS запись (тип A), создающую соответствие между IP адресом каждого сервера RD Session Host и DNS именем фермы.

Я опишу процедуру настройки DNS записей на контроллере домена Windows Server 2008 R2. Сразу стоит отметить, что для выполнения данной процедуры у вас должны быть права Domain Admins/ Enterprise Admins / DNS Admins.

  • Откройте оснастку DNS (Start->Administrative Tools-> DNS).
  • Разверните сервер, и в зонах прямого просмотра (Forward Lookup Zones), разверните ветку с именем вашего домена.
  • Щелкните по зоне и выберите New Host (A or AAAA).
  • В поле Name укажите имя фермы (именно фермы, а не конкретного сервера в ней), а в поле IP address укажите ip адрес первого сервера в ферме.

Эти действия необходимо повторить для каждого из серверов-членов фермы RDS (в каждом случае меняться будет только ip адрес)

Проверим, что наша ферма создалась, для чего откройте Remote Desktop Services Manager. Щелкните правой кнопкой по Remote Desktop Services Manager и выберите Import from RD Connection Broker и укажите FQDN имя сервера с ролью Connection broker(в моем случае RDS01.сайт)

Теперь в дереве RD Connection Broker появится новая терминальная ферма!

Если у вас очень популярный сайт, со временем сервер, на котором он расположен, достигнет предельной нагрузки, в результате которой больше не сможет обрабатывать входящие запросы.
На языке IT это явление называется Слэшдот-эффект (мощный всплеск посещаемости веб-сайта). Добавление оперативной памяти, апгрейд процессоров и использование быстрых дисков и шин поможет в краткосрочной перспективе, но в результате вы все равно обнаружите, что одна машина не сможет выдерживать требуемую нагрузку.
Один из способов обеспечения отказоустойчивости сайта – это балансировка нагрузки серверов . Путем добавления второй (или третьей) машины в доступный пул оборудования, вы можете не только увеличить производительность, но и повысить отказоустойчивость сервера . Если у вас есть машина горячего резерва (или несколько), работающая(ие) постоянно, то в случае, когда основной сервер испытывает проблемы, другие могут выполнять его работу без простоя.

Балансировка нагрузки серверов с помощью Round-robin DNS

Возможно, самый простой способ преодоления Слэшдот-эффекта – это метод балансировки нагрузки серверов с помощью Round-robin DNS . При этом входящие запросы к веб-сайту могут быть отправлены на любое количество машин.
В BIND 9 есть возможность для одного домена создать несколько А-записей. Например, предположим, что мы используем в файле зоны домена для example .com:

Www 60 IN A 10.0.0.1
www 60 IN A 10.0.0.2

При определении А-записи для www.example .com в DNS, в половине случаев пользователи увидят:

Host www.example .com
www.example .com has address 10.0.0.1
www.example .com has address 10.0.0.2

А в другой половине:

Host www.example .com
www.example .com has address 10.0.0.2
www.example .com has address 10.0.0.1

Поскольку большинство приложений используют только первый адрес, возвращаемый DNS, то этот метод работает достаточно хорошо. Запросы распределяются между веб-серверами примерно пополам, и, таким образом, нагрузка на каждый из них уменьшается приблизительно в два раза.
В примере TTL установлен равным 60 секундам, для того чтобы предотвратить влияние кэширующих серверов DNS. Это должно помочь поддержанию более или менее равного количества запросов к каждому серверу.
Технология Round-robin DNS используется для балансировки нагрузки только в случае, когда произведена настройка зеркального копирования (зеркалирования) данных для всех серверов . Если это не так, то браузер может сначала показать одну версию страницы сайта, а после нажатия кнопки «Обновить» - другую.

С появлением кластеров с балансированием сетевой нагрузки (Network Load Balancing - NLB ) рулетка стала не так популярна, но она иногда реализуется с целью предоставления статического распределения нагрузки, например, между двумя одинаково настроенными кластерами. Статическое распределение нагрузки с помощью сервера является простым в настройке. Для этого требуется указать несколько записей A для одного узла с разными адресами IP. После этого достаточно включить рулетку (round robin ). Использование в настройках зоны нескольких записей A позволяет предоставлять клиенту разные адреса IP при каждом запросе на преобразование данного имени.

Предположим, что существует четыре адреса IP для узла под именем www.windata.ru. Первый клиент, который отправляет запрос на преобразование имени, получает адрес 10.0.0.10, второй клиент может получить адрес 10.0.0.11. Следующие два ответа будут содержать адреса 10.0.0.12 и 10.0.0.13. Пятый запрос на преобразование имени заставит сервер DNS вернуть адрес 10.0.0.10, возвращаясь к началу списка адресов.

Иногда реализации рулетки терпят неудачу из-за незавершенного конфигурирования. Администраторы вносят в данные зоны несколько записей A, но забывают включить использование рулетки в конфигурации сервера DNS.

Использование Round Robin

В таком случае адрес из первой записи всегда выдается сервером DNS на входящие запросы. Рулетка может быть включена с помощью флажка Включить рулетку (Enable Round Robin ) на вкладке Дополнительно (Advanced) диалогового окна Свойств (Properties) сервера DNS .

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

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