Балансировка нагрузки в распределенных системах. Проектировщики

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

Следует различать декомпозицию задач и проблему отображения задач на вычислительную среду. Декомпозиция задачи является этапом процесса создания параллельной программы. Декомпозиция предназначена для разделения приложения на модули (задачи). Задачи исполняются на отдельных процессорах. В результате декомпозиции распределенного приложения появляется набор задач, которые параллельно решают задачу. Эти задачи могут быть независимыми или связанными друг с другом посредством обмена данными. Отображение (или "распределение задач") является отдельным этапом, позволяющим распределить задания, полученные на этапе декомпозиции, между процессорами.

Итак, будем считать, что распределенное приложение представляет собой совокупность логических процессов, которые взаимодействуют друг с другом, посылая друг другу сообщения. Логические процессы распределяются по разным вычислительным узлам и могут функционировать параллельно. При распределении логических процессоров по вычислительным узлам их стараются распределять так, чтобы вычислительных узлов была равномерной.

Однако при выполнении распределенного приложения возникает конфликт между сбалансированным распределением объектов по процессорам и низкой скоростью обменов сообщениями между процессорами. Если логические процессы распределены между процессорами таким образом, что издержки на коммуникацию между ними сведены к нулю, то некоторые процессоры (компьютеры) могут простаивать, в то время как остальные будут перегружены. В другом случае, "хорошо сбалансированная" система потребует больших затрат на коммуникацию. Следовательно, стратегия балансировки должна быть таковой, чтобы вычислительные узлы были загружены достаточно равномерно, но и коммуникационная среда не должна быть перегружена.

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

Балансировка вычислительной нагрузки

Причины возникновения несбалансированной нагрузки

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

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

Статическая и динамическая балансировки

Следует различать статическую и динамическую балансировки.

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

Это объясняется тем, что:

  • Может измениться вычислительная среда, в которой происходит выполнение приложения, какой либо вычислительный узел может выйти из строя.
  • Вычислительный узел, на котором выполняется распределенное приложение, занят ещё и другими вычислениями, доля которых со временем может возрасти.

Так или иначе, выигрыш от распределения логических процессов по компьютерам с целью выполнения параллельной обработки становится неэффективным.

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

  • загрузку вычислительных узлов;
  • пропускную способность линий связи;
  • частоту обменов сообщениями между логическими процессами распределенного приложения и др.

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

Постановка задачи динамической балансировки

Цель балансировки загрузки может быть сформулирована следующим образом:

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

Представим распределенное приложение в виде графа. Пусть G p = {V, E} , V –множество вершин (задачи распределенного приложения), E – множество дуг графа – связи между задачами распределенного приложения. Пусть TM – множество моделей распределенных приложений, .

Задача балансировки ставится как задача отображения неизоморфных связных графов, B: TM -> NG , где TM – множество графов моделей, NG – множество графов – конфигураций компьютерной сети. Граф , определяется множеством вычислительных узлов C и множеством ребер Ed , обозначающих линии связи. Можно рассматривать NG как суперграф, содержащий все возможные (допустимые) графы G в качестве подграфов .

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

Методология практического решения задачи балансировки

Обычно практичное и полное решение задачи балансировки загрузки состоит из четырех шагов:

  • Оценка загрузки вычислительных узлов.
  • Инициация балансировки загрузки.
  • Принятие решений о балансировке.
  • Перемещение объектов.

В последующих частях конкретизируется каждый шаг балансировки с рассмотрением различных методов решения.

Что есть балансировка нагрузки? Фактически, это распределение входящих сетевых подключений между несколькими вычислительными узлами. При этом, использование для этих целей аппаратных или программных решений, а так же применяемый алгоритм распределения сути, совершенно не меняет. Но, благодаря распределению нагрузки можно решить две достаточно серьезные проблемы.
Во-первых, это распределение нагрузки между вычислительными узлами в ситуации, когда ресурсов одного сервера не достаточно и вертикальное наращивание его мощности уже не возможно. В таком случае, необходимо добавление еще одной вычислительной единицы и применение одного из видов балансировки.
Во-вторых — обеспечение доступности. Как известно, отказоустойчивость любой системы, будь то аппаратное решение или программное достигается путем дублирования основных компонентов. К сожалению, не существует абсолютно надежных жестких дисков, RAID-контроллеров и прочего оборудования, а современный уровень программирования не гарантирует отсутствие сбоев в ПО. По этой причине, при построении отказоустойчивых сервисов, дублируется все, сетевые контроллеры, коммутаторы и в конце концов сами вычислительные узлы. Например, нагрузка создаваемая на один сервер может быть не большой, но при этом хочется, что бы выход одного или нескольких узлов не привел к простою сервиса. В этом случае решением снова может стать балансировщик нагрузки.

Основные виды и техники балансировки

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

Примитивные методы

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

Round robin DNS (циклический перебор)

Пожалуй, самый распространенный метод. Основан на том, что спецификация DNS позволяет создавать несколько одинаковых А-записей с отличными IP-адресами. Например, можно завести две записи для узла srv-01.company.com с различными IP-адресами принадлежащих, разным серверам. Дополнительно, должна быть включена специальная опция (Round robin) на DNS-сервере. В результате, при каждом новом запросе записи srv-01.company.com будут отдаваться разные IP-адреса, что приведет к равномерному распределению подключений между узлами.
Но, при всей легкости и дешевизне данного решения, имеется ряд ограничений. Во первых, нет никаких методов проверки доступности узлов. То есть, сервер может выйти из строя, но DNS все равно будет отдавать его IP-адрес клиентам. Во вторых, не учитывается число текущих сессий на том или ином узле. Может получиться ситуация, когда на одном из серверов, открытых сессий значительно больше чем на остальных, при этом подключения все равно будут распределяться равномерно. Ну и в-третьих, DNS не учитывает к какому серверу был подключен пользователь в прошлый раз. Возможно, что при каждом новом подключении, например, к терминалу или к веб-серверу, будет открываться новая сессия на другом узле, что может быть не желательно.
Отдельно, в этом пункте хочется выделить сервисы типа Amazon Route 53 . Это облачный DNS-хостинг позволяющий кроме стандартных функций, указывать «вес» одинаковых А-записей, что позволяет распределять входящие запросы более гибко. Кроме этого, возможна интеграция с облачным балансировщиком нагрузки Elastic Load Balancing доступным в Amazon Web Services, что позволяет добиться еще более тонкой балансировки.

Так же, к примитивным методам можно отнести балансирование вручную

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

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

Это самый универсальный и распространенный механизм. Одинаково применим для TCP и UDP протоколов, а соответственно им можно распределять трафик практически любого сервиса. На этом уровне во входящих пакетах проверяется лишь IP-адрес и номер порта назначения. В случае совпадения с одним из правил, трафик будет попросту перенаправлен на указанные сервера, с помощью механизма sNAT в установленном порядке. Содержимое пакетов не проверяется. Так же нет никаких особых техник проверки доступности вычислительных узлов. Выполняется простая проверка доступности адреса и порта. В случае если порт открыт, сервер считается доступным и к нему продолжают отправляться запросы.
По такому механизму работает большинство популярных программных и аппаратных балансировщиков, в том числе Network Load Balancing (NLB) используемый в Windows Server. Так же, к этой категории можно отнести популярные нынче облачные сервисы типа Elastic Load Balancing от Amazon, упомянутый выше.

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

Динамично развивающийся вид распределения нагрузки на уровне приложений. Такие балансировщики еще называют контроллерами доставки приложений. Ориентированы на работу с высокоуровневыми протоколами. В основном HTTP\HTTPS. Здесь, как и в случае с предыдущим видом описываются правила. При установке соединения на некотором порту, пакеты перенаправляются на указанные адреса и порты вычислительных узлов. Но, при выборе конкретного сервера для ретрансляции на него трафика, учитывается тип клиента, URL, содержимое cookie, запрашиваемый контент и некоторые другие параметры. Кроме этого, проверка доступности сервиса на вычислительных узлах, проверяется значительно интеллектуальнее. Например, может запрашиваться некоторый URL и проверяться его содержимое.
Еще одной отличительной чертой этого типа от L4 является то, что сервера в кластере могут быть не идентичными. Например, одни узлы могут поставлять статические данные типа фото и видео а другие серверы доставляют контент с помощью скриптов, HTML и CSS. В таком случае, могут быть созданы правила для каждого типа контента с особыми алгоритмами перенаправления трафика на различные группы серверов. В этой категории, так же существует еще один класс профильных балансировщиков, типа Citrix NetScaler . Это решение специализируется на распределении нагрузки и повышении производительности продуктов Citrix (XenApp, XenDesktop), а так же веб-приложений. Кроме продвинутой балансировки он умеет выполнять компрессию контента, мощное кэширование, обеспечивает шифрование, а так же анализ трафика и его фильтрацию. Это лишь небольшая часть его возможностей, которые заслуживают отдельной статьи.

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

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

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

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

Процедура балансировки осуществляется при помощи целого комплекса алгоритмов и методов, соответствующим следующим уровням модели 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 — подробнее об этом можно прочитать, например,

Заключение

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

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

Теги:

  • load balancing
  • селектел
  • selectel
Добавить метки

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

Типы серверов, которые должны быть сбалансированы:

    серверные кластеры;

    межсетевые экраны;

    серверы инспектирования содержания (такие как AntiVirus- или AntiSpam- серверы).

Обычно системы балансировки загрузки серверов используют возможности уровня L4 (UDP/TCP). При этом контролируется доступность сервера по IP-адресу и номеру порта и принимается решение: какому из доступных серверов следует переслать запрос. Наиболее часто для выбора сервера используется карусельный алгоритм (round-robin). В этом варианте предполагается, что все запросы создают одинаковую загрузку и длительность исполнения. В более продвинутых вариантах алгоритма используется уровень занятости сервера и число активных соединений.

Раньше возможности балансировки нагрузки встраивались в саму прикладную программу или операционную систему. Современные системы балансировки нагрузки должны удовлетворять следующим требованиям:

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

    ускорять выполнение приложений в несколько раз;

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

Здесь важно учитывать, что доступность IP-адреса и порта еще не гарантирует доступа к приложению.

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

Довольно существенные преимущества может предоставить система GSLB (Global Server Load Balancing), которая способна решать задачу балансировки для произвольно расположенных ферм серверов с учетом их удаленности от клиента. Эта система может поддерживать несколько разных алгоритмов распределения нагрузки и обеспечивать оптимальное обслуживание клиентов, разбросанных по всему миру. Для администраторов система дает возможность формирования гибкой политики управления ресурсами.

Одним из способов ускорения обслуживания является кэширование. В случае хорошо сконфигурированного кэша доля запросов, удовлетворяемых кэшем, может достигать 40%. При этом ускорение обслуживания может быть улучшено в 30 раз.

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

Управление балансировкой нагрузки можно совместить с функцией прикладного межсетевого экрана (70% успешных вторжений использует уязвимости приложений) и с использованием SSL по VPN-туннелю. SSL – Secure Sockets Layer – криптографический протокол, который обеспечивает установление безопасного соединения между клиентом и сервером.

Для достижения максимальной пропускной способности и отказоустойчивости межсетевые экраны позволяют распределить или сбалансировать нагрузку, используя все имеющиеся каналы Интернета (серверов) одновременно. Например, можно избежать такой ситуации, когда передаваемые по сети пакеты идут через одного провайдера, в то время как выход в Интернет через другого провайдера простаивает без дела. Или распределить сервисы и направить трафик через все имеющиеся Интернет-каналы. Возможна настройка балансировки нагрузки, если соединения с провайдерами осуществляются с разными типами подключения (Static IP, PPPoE, PPTP/L2TP), а также – для балансировки трафика, проходящего через VPN-туннели, установленные на разных физических интерфейсах.

Рис. 4.12. Балансировка нагрузки по нескольким маршрутам

В межсетевых экранах D-Link серии NetDefend предусмотрена функция, предназначенная для балансировки сетевой нагрузки по разным маршрутам – Route Load Balancing (RLB ) , возможности которой обеспечивают:

    балансировку трафика между интерфейсами на основе политик;

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

    балансировку трафика, проходящего через VPN-туннели, установленные на разных физических интерфейсах.

Функция балансировки нагрузки в межсетевых экранах NetDefend активируется на основе таблицы маршрутизации путем создания объекта RLB Instance , в котором определены два параметра: таблица маршрутизации и RLB-алгоритм. С таблицей маршрутизации может быть связан только один объект Instance.

Рис. 4.13. Выбор алгоритма распределения нагрузки в межсетевых экранах NetDefend

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

    Алгоритм Round Robin распределяет нагрузку между интерфейсами WAN1 и WAN2 последовательно (поочередно). Каждый раз, когда возникает новая исходящая сессия с интерфейса LAN, выбирается интерфейс WAN1 или WAN2 для отправки пакетов. В дальнейшем, пакеты данной сессии будут использовать ранее определенный WAN-интерфейс. TCP-сессия открывается и закрывается на одном и том же WAN-интерфейсе.

    Алгоритм Destination позволит избежать проблем с некоторыми протоколами при использовании балансировки, например FTP. Данный алгоритм работает аналогично алгоритму Round Robin, за исключением того, что все данные к удаленному хосту идут через тот интерфейс, через который соединение было установлено.

    Значение Spillover определяет предельное значение нагрузки для основного WAN-порта (Routing → Route Load Balancing > Algoritm Setings ) . При достижении этой нагрузки за указанный период начнет использоваться второй WAN-порт (для новых сессий). Как только загрузка основного канала упадет, новые сессии будут открываться на нем.

Round Robin

Метрика каждого маршрута по умолчанию равна нулю. При использовании взаимосвязанных алгоритмов Round Robin и Destination можно устанавливать разные значения метрик, позволяющие создать приоритет выбора маршрутов. Маршруты с минимальным значением метрики будут выбираться чаще, чем маршруты с более высоким значением.

Если в сценарии с двумя Интернет-провайдерами (часто встречается выражение "ISP-провайдер", т.е. Internet Service Provider) требуется, чтобы большая часть трафика проходила через одно из ISP-подключений, то следует активировать RLB и назначить меньшее значение метрики для маршрута основного ISP-подключения (например, 90) относительно второго (например, 100).

Если задача заключается в равномерной балансировке трафика между двумя Интернет-провайдерами, то значение метрик для обоих маршрутов следует назначать одинаковое.

Использование метрик маршрута с алгоритмом Spillover

При использовании алгоритма Spillover для каждого маршрута обязательно должна быть определена метрика. В этом случае система NetDefendOS всегда выбирает маршрут с самым низким значением метрики. Алгоритм не предназначен для работы с одинаковыми метрическими значениями маршрутов, поэтому администратору следует устанавливать различные значения метрик для всех маршрутов, к которым применяется алгоритм Spillover .

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

Можно создать несколько альтернативных маршрутов с различными метрическими значениями, для каждого из которых определена пороговая величина настроек алгоритма – Spillover Setting – для каждого интерфейса. Сначала выбирается маршрут с минимальной метрикой; после того как превышен допустимый порог настроек алгоритма, будет выбран следующий маршрут.

Если на всех альтернативных маршрутах достигнуты пороговые значения Spillover Setting, то маршрут не меняется.

ВНИМАНИЕ : значение метрики на интерфейсах (маршрутах), которые используются в балансировке, должно быть установлено выше, чем для остальных интерфейсов (маршрутов). Чем ниже значение метрики на интерфейсе (маршруте), тем чаще этот интерфейс (маршрут) будет использован для установки соединения, относительно интерфейса (маршрута) с большим значением метрики. Доля использования интерфейсов (маршрутов) будет пропорциональна разнице между значениями метрик на этих интерфейсах (маршрутах).

Балансировка нагрузки сети и НА-кластеризация (резервирование устройств) межсетевых экранов NetDefend

Высокий уровень сетевой отказоустойчивости достигается за счет использования двух межсетевых экранов NetDefend: основного устройства (master) и резервного устройства (slave). Основной и резервный межсетевые экраны взаимосвязаны и составляют логический HA-кластер.

Межсетевые экраны NetDefend не поддерживают балансировку нагрузки в НА-кластеризации устройств, т.е. распределение нагрузки между ними не обеспечиваетс , так как одно устройство всегда является активным (active), в то время как другое находится в режиме ожидания (passive).

Рис. 4.14. НА-кластеризация межсетевых экранов NetDefend

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

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

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

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

Процедура балансировки осуществляется при помощи целого комплекса алгоритмов и методов, соответствующим следующим уровням модели 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 — подробнее об этом можно прочитать, например,

Заключение

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

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

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