Microsoft Azure предлагает сервис балансировки нагрузки для виртуальных машин (IaaS) и облачных служб (PaaS), запущенных в облаке Microsoft Azure. Помимо прочих достоинств, балансировка нагрузки позволяет масштабировать ваши приложения и дает возможность мягче реагировать при возникновении ошибки или отказа.
Службы балансировки нагрузки могут быть задействованы как с помощью настроек на портале управления Microsoft Azure, так и с помощью сервис-модели вашего приложения. Как только размещаемая служба с одной или несколькими конечными точками публикуется в облако, она автоматически настраивается на использование балансировщика нагрузки, предоставляемого платформой Microsoft Azure. Чтобы получить все плюсы эластичности и масштабируемости вам необходимо иметь хотя бы две виртуальных машины, настроенных на одну и ту же конечную точку.
Диаграмма на рисунке ниже показывает пример приложения, расположенного в Microsoft Azure, которая использует балансировщик нагрузки для адресации входящего трафика (по адресу/порту 1.2.3.4:80) на три виртуальных машины, слушающих 80-й порт (кликабельно).
Далее перечислены основные возможности балансировщика нагрузки в Microsoft Azure
Поддержка IaaS / PaaS
Балансировка нагрузки работает со всеми типами сервисов (IaaS и PaaS) и со всеми операционными системами (Windows или любой Linux-дистрибутив).
Приложения в PaaS конфигурируются с помощью сервис-модели. Виртуальные машины IaaS настраиваются либо через портал управления, либо с помощью PowerShell.
Балансировщик Layer-4, распределение по хешу
Балансировщик нагрузки в Microsoft Azure имеет тип Layer-4. Это значит, что он распределяет нагрузку между всеми доступными виртуальными машинами путем вычисления хеш-функции от трафика, поступившего на данную конечную точку. Эта хеш-функция вычисляется таким образом, что все пакеты, поступившие в рамках одного соединения (TCP или UDP) направляются на один и тот же сервер. Балансировщик Microsoft Azure использует набор из 5 полей (IP адрес источника, порт источника, IP адрес назначения, порт назначения, тип протокола) для вычисления хеша, используемого при сопоставлении трафика и доступного сервера. К тому же хеш-функция подбиралась таким образом, чтобы распределения соединений к серверам были достаточно случайными. Однако в зависимости от типа трафика допустимо, что разные соединения будут привязаны к одному и тому же серверу. (Также нужно заметить, что распределение соединений к серверам НЕ являются round-robin, а также НЕТ никакой очереди запросов, как было иногда написано ранее в некоторых статьях и блогах). Базовая хеш-функция позволяет получить неплохое распределение запросов при достаточно большом их количестве из разных источников.
Поддержка нескольких протоколов
Служба балансировки нагрузки в Microsoft Azure поддерживает протоколы TCP и UDP. Клиенты могут указать тип протокола при настройке входящих конечных точек в сервис-модели, с помощью PowerShell или на портале управления.
Поддержка нескольких конечных точек
Размещенная в облаке служба может указать несколько входящих конечных точек и они автоматически будут настроены в сервисе балансировщика нагрузки.
На текущий момент несколько конечных точек, у которых совпадают порт и протокол не поддерживаются. Также есть ограничение на максимально доступное количество конечных точек, которых сейчас может быть до 150 штук.
Поддержка внутренних конечных точек
Каждый сервис может указать до 25 конечных точек, которые не будут участвовать в балансировке. Такие точки можно использовать для внутренней коммуникации между сервисами.
Поддержка прямых конечных точек
Размещаемая служба может указать, что данная конечная точка должна иметь прямой доступ к виртуальной машине извне в обход балансировщика. Это позволит приложению управлять возможным перенаправлением пользователя напрямую к виртуальной машине, не пользуясь услугами балансировщкиа (а как следствие, вероятность попадания запросов на разные узлы).
Автоматическое изменение конфигурации при масштабировании вверх/вниз, обновлении и профилактики сервиса
Балансировщик нагрузки работает в связке с Microsoft Azure Compute Service, чтобы быть уверенным в том, что если количество серверов для конечных точек масштабируется вверх/вниз (либо при повышении количества экземпляров для веб или рабочей роли, либо при добавлении новых виртуальных машин в одну группу балансировки), балансировщик автоматически перенастраивает себя под эти изменения.
Балансировщик нагрузки также незаметно изменяет свои настройки в ответ на профилактические действия fabric-контроллера или служебные обновления клиента.
Мониторинг
Балансировщик нагрузки Microsoft Azure предоставляет возможность мониторинга работоспособности различных сервисных экземпляров и удаления нездоровых экземпляров из ротации балансировки. Есть три типа проверок: проверка Guest Agent (для PaaS), HTTP-проверки и TCP-проверки. В случае Guest Agent, служба балансировщика запускает специального агента на соответствующей виртуальной машине для получения статуса сервиса. В случае HTTP-теста балансировщик нагрузки полагается на опрос заданного URL для определения жизнеспособности приложения. Если выбран TCP-тест, то балансировщик полагается на результат установки TCP-соединения по определенному порту.
Source NAT
Весь обратный трафик, исходящий из сервиса, является Source NAT (SNAT), используя тот же самой виртуальный IP-адрес, что и для входящего трафика. Мы расскажем о SNAT подробнее в следующих сообщениях.
Оптимизация трафика в пределах ЦОД
Балансировщик нагрузки Microsoft Azure оптимизирует трафик между ЦОД в одном регионе таким образом, что размещения, которые общаются между собой через виртуальный IP-адрес (VIP) и находятся в одном регионе, после установления TCP/IP-соединения, вместе проходят через балансировщик нагрузки.
Обмен виртуальным IP-адресом
Балансировщик нагрузки Microsoft Azure позволяет менять VIP двух узлов, перемещая один узел из тестового состояния в продуктив и наоборот. Операция смены VIP позволяет клиентам использовать один VIP для общения с сервисом, в то время, как новая версия сервиса находится в процессе размещения (deploy). Новая версия может быть размещена и протестирована без влияния на основное приложение, в тестовом окружении. Как только новая версия пройдет все проверки, она может быть введена в промышленную эксплуатацию путем «отбора» VIP у текущей виртуальной машины и присвоения его новой. При этом все текущие соединения к старой машине остаются нетронутыми, а новые соединения направляются на «новый» сервер.
Пример: сервис балансировки нагрузки
Далее мы посмотрим, как большинство из описанного выше могут быть использованы в облачной службе. Модель PaaS-окружения, которое хотим получить, изображена ниже:
Данное решение имеет две роли Frontend (FE) и одну роль Backend (BE). Роль FE открывает четыре балансированные конечные точки, используя протоколы http, tcp и udp. Одна из точек также используется для мониторинга производительности. Роль BE открывает три конечные точки с протоколами http, tcp и udp. Обе роли (FE и BE) имеют по одной прямой конечной точке на соответствующий экземпляр сервиса.
Сервисы, описанные ниже, конфигурируется с помощью сервис-модели (некоторые особенности схемы были удалены для удобства чтения):
<ServiceDefinition name="ProbeTenant">
<LoadBalancerProbes>
<LoadBalancerProbe name="MyProbe" protocol="http" path="Probe.aspx" intervalInSeconds="5" timeoutInSeconds="100" />
</LoadBalancerProbes>
<WorkerRole name="BERole" vmsize="Small">
<Endpoints>
<InternalEndpoint name="BE_InternalEP_Tcp" protocol="tcp" />
<InternalEndpoint name="BE_InternalEP_Udp" protocol="udp" />
<InternalEndpoint name="BE_InternalEP_Http" protocol="http" port="80" />
<InstanceInputEndpoint name="InstanceEP_BE" protocol="tcp" localPort="80">
<AllocatePublicPortFrom>
<FixedPortRange min="10210" max="10220" />
</AllocatePublicPortFrom>
</InstanceInputEndpoint>
</Endpoints>
</WorkerRole>
<WorkerRole name="FERole" vmsize="Small">
<Endpoints>
<InputEndpoint name="FE_External_Http" protocol="http" port="10000" />
<InputEndpoint name="FE_External_Tcp" protocol="tcp" port="10001" />
<InputEndpoint name="FE_External_Udp" protocol="udp" port="10002" />
<InputEndpointname="HTTP_Probe" protocol="http" port="80" loadBalancerProbe="MyProbe" />
<InstanceInputEndpoint name="InstanceEP" protocol="tcp" localPort="80">
<AllocatePublicPortFrom>
<FixedPortRange min="10110" max="10120" />
</AllocatePublicPortFrom>
</InstanceInputEndpoint>
<InternalEndpoint name="FE_InternalEP_Tcp" protocol="tcp" />
</Endpoints>
</WorkerRole>
</ServiceDefinition>
Рассмотрим данную модель. Мы начинаем с того, что определяем тип тестирования производительности, который должен использовать балансировщик для проверки работоспособности сервиса:
<LoadBalancerProbes>
<LoadBalancerProbe name="MyProbe" protocol="http" path="Probe.aspx" intervalInSeconds="5" timeoutInSeconds="100" />
</LoadBalancerProbes>
Здесь сказано, что мы хотим использовать тестирование через HTTP, используя относительный путь «Probe.aspx». Данный тест будет позднее подключен к конечной точке.
Затем мы определяем роль EF как WorkerRole. Она имеет несколько конечных точек (http, tcp, udp)
<InputEndpoint name="FE_External_Http" protocol="http" port="10000" />
<InputEndpoint name="FE_External_Tcp" protocol="tcp" port="10001" />
<InputEndpoint name="FE_External_Udp" protocol="udp" port="10002" />
До тех пор, пока мы не настроили собственный мониторинг производительности, тестирование на работоспособность производится с помощью гостевого агента и может быть изменено сервисом с помощью события StatusCheck.
Затем мы определяем дополнительную конечную точку для 80-го порта, который использует собственный тест (MyProbe)
<InputEndpoint name="HTTP_Probe" protocol="http" port="80" loadBalancerProbe="MyProbe" />
Балансировщик нагрузки комбинирует информацию о конечной точке и о тестировании, чтобы получить URL вида http://{DIP of VM}:80/Probe.aspx, который затем будет использоваться при тестировании работоспособности сервиса. Сервис будет понимать (по логам ?), что один и тот же IP-адрес периодически обращается к нему. Это и есть запросы о состоянии, поступающие от узла, где размещена виртуальная машина.
Сервис должен ответить с HTTP кодом 200, чтобы балансировщик считал его работоспособным. Любой другой код состояния выводит виртуальную машину из ротации.
Настройка тестирования также задает периодичность опросов. В нашем случае балансировщик опрашивает сервис каждые 15 секунд. Если ответ не был получен в течение 30 секунд (два интервала опроса), тест считается проваленным и виртуальная машина выводится из ротации. Аналогично, если виртуальная машина выведена из ротации, но от нее начал приходить положительный ответ, этот сервис сразу же возвращается в ротацию. Если сервис долго находится в режиме работает/не работает, балансировщик нагрузки может сам принять решение о задержке на ввод в ротацию до тех пор, пока тот не будет реагировать положительно на достаточное количество тестов.
Сервис FE также предоставляет набор прямых конечных точек, одна на каждый экземпляр, которая соединяется с экземпляром напрямую по указанному порту:
<InstanceInputEndpoint name="InstanceEP" protocol="tcp" localPort="80">
<AllocatePublicPortFrom>
<FixedPortRange min="10110" max="10120" />
</AllocatePublicPortFrom>
</InstanceInputEndpoint>
Определение выше устанавливает соединение по портам 10110, 10111 и т.д. и переводит его на порт 80 для всех виртуальных машин с FE ролями. Такая функция может быть использована в нескольких сценариях:
- Предоставить доступ к заданному экземпляру и производить действия только с ним
- Перенаправить пользовательское приложение на конкретный экземпляр после того, как тот прошел через балансированную конечную точку. Это может быть использовано для «липких» (sticky) сессий. Но стоит иметь в виду, что это может привести к перегрузке данного экземпляра.
Наконец, роль FE предоставляет внутреннюю конечную точку, которая может быть использована для взаимодействия между FE и BE:
<InternalEndpoint name="FE_InternalEP_Tcp" protocol="tcp" />
Каждая роль может получать доступ к своим конечным точкам, а также к точкам, которые предоставляют другие роли, используя класс RoleEnvironment.
Роль BE также настроена как WorkerRole. Она не предоставляет никаких балансированных конечных точек, только внутренние точки, использующие http, tcp и udp:
<InternalEndpoint name="BE_InternalEP_Tcp" protocol="tcp" />
<InternalEndpoint name="BE_InternalEP_Udp" protocol="udp" />
<InternalEndpoint name="BE_InternalEP_Http" protocol="http" port="80" />
Роль BE также дает прямую конечную точку, которая позволяет соединяться напрямую с экземпляром BE:
<InstanceInputEndpoint name="InstanceEP_BE" protocol="tcp" localPort="80">
<AllocatePublicPortFrom>
<FixedPortRange min="10210" max="10220" />
</AllocatePublicPortFrom>
</InstanceInputEndpoint>
Определение выше устанавливает соединение по портам 10110, 10111 и т.д. и переводит его на порт 80 для всех виртуальных машин с BE-ролями.
Мы надеемся, что пример выше покажет вам, как использовать различные возможности балансировщика нагрузки вместе при моделировании сервисов.