Решение задачи балансировки нагрузки в большинстве случаев кажется простой и банальной. Но дьявол обычно кроется в деталях. Сегодня мы разберем в каких случаях без балансировщика не обойтись и как выбрать лучший метод балансировки.
Прежде всего рассмотрим сам процесс работы типичного Web-приложения:
- Запрос пользователя попадает на Front-end.
- Front-end делает запрос в Back-end.
- Back-end отдает ответ на Front-end.
- Front-end формирует и отдает пользователю результат.
Если у нас есть только один Front-end и один Back-end, то балансировать тут особо и нечего. Усложним задачу. Теперь у нас есть один Front-end и два Back-end сервера. Если балансировщик отсутствует вообще и программно не настроено распределение запросов, то один Back-end всегда будет простаивать, а второй принимать на себя всю нагрузку. Так или иначе нужно распределить запросы между двумя серверами.
И вот мы плавно переходим к методам балансировки. В нашем Балансировщике нагрузки для Облачной платформы Selectel реализовано два самых эффективных и часто используемых алгоритма:
- Round Robin (циклический алгоритм);
- Least connections (алгоритм наименьших соединений).
Рассмотрим каждый из алгоритмов подробнее.
Round Robin
Этот алгоритм очень прост для понимания. Запросы отправляются на все балансируемые серверы попеременно. Так что, в описываемом нами случае с одним Front-end и двумя Back-end серверами все выглядит просто замечательно. В идеальном варианте у нас нагрузка на каждый Back-end будет распределена равномерно, то есть 50% на 50%. Но есть одна серьезная проблема.
Несмотря на то, что запросы равномерно распределились по серверам, их обработка будет занимать разное время. А это значит, что через N-ное количество запросов загрузка обоих Back-end серверов станет различной. Это не будет являться проблемой ровно до того момента, пока один из них не начнет отдавать в ответ ошибки.
Для пользователя такие ошибки будут выражаться в том, что запрашиваемые функции просто перестанут адекватно работать, например, пользователь не сможет «положить товар в корзину». С точки зрения бизнеса подобные ошибки равноценны упущенной прибыли, а следовательно, к вопросу балансировки следует подойти еще более ответственно.
Least connections
Теперь, зная потенциально уязвимое место алгоритма Round Robin, перейдем ко второму алгоритму Least connections. Суть его в том, что балансировщик смотрит сколько соединений установлено на каждом из подконтрольных ему серверов и определяет минимально загруженный. Именно на него начинают отправляться новые запросы.
Казалось бы, вот он — идеальный механизм балансировки. Серверы будут равномерно загружены вне зависимости от времени исполнения запросов. Но это справедливо ровно до того момента, пока перед нами не встает необходимость балансировки нагрузки между двумя и более Front-end серверами.
Когда пользователь установил соединение с одним из Front-end сервером, то все его последующие запросы нужно отправлять на тот же самый сервер. Если же будет отрабатывать только алгоритм Least connections, то мы создаем ситуацию, когда установивший сессию пользователь может быть направлен на другой Front-end. И это означает повторную необходимость в авторизации, чего быть не должно. Тут на помощь нам приходит такая полезная опция балансировщика, как Sticky sessions.
Sticky sessions
Название говорит само за себя. Указанный механизм заставляет балансировщик направлять запрос одного и того же пользователя на один и тот же Front-end сервер. Для этого балансировщику нужно опознать пользователя, используя один из трех доступных вариантов:
- по ARP-cookie;
- по HTTP-cookie;
- используя Source IP.
Каждый из вариантов имеет право на существование, но нужно тщательно понимать какой именно выбрать.
- ARP-cookie в большинстве случаев идеален для сложных веб-приложений, но выдачу этого фрагмента данных необходимо заранее реализовать в коде приложения.
- HTTP-cookie — отличный вариант для авторизации пользователя. Балансировщик вначале задействует алгоритм Least connections для выбора сервера, а затем прикрепляет собственный HTTP-cookie, чтобы последующие запросы клиента отправлялись только на тот же самый сервер.
- Source IP — тут тоже все вроде просто. Балансировщик смотрит на соответствующее поле пакета и все запросы с одного IP-адреса отправляет на один и тот же Front-end сервер. При этом балансировщик еще и учитывает параметр «вес» подконтрольных серверов, но об этом поговорим ниже.
Отметим, что вариант Source IP имеет очень серьезный «подводный камень», а именно пользователей, которые приходят из сетей мобильных операторов связи. В некоторых случаях сотни пользователей могут приходить с одного-единственного IP-адреса. И все они будут заботливо отправлены балансировщиком на один Front-end сервер, который вполне может и лечь под нагрузкой. Так что, выбирая этот вариант, нужно учитывать возможность возникновения подобной ситуации.
Тюнинг балансировки
«Вес» сервера
Мы рассказали, как выбрать идеальный для вас вариант балансировки для каждого из сервисов. Тем не менее, это не исключает возникновения ситуации, когда трафик будет распределен с перекосом в сторону одного или нескольких подконтрольных серверов. Поэтому помимо автоматической работы алгоритмов мы предусмотрели возможность ручного воздействия на поведение балансировщика.
Сама собой напрашивается аналогия с автоматической коробкой переключения передач в машине, где есть псевдо-ручной режим (TipTronic / AutoStick / Steptronic / Multitronic и другие). Автомобиль управляется автоматической коробкой переключения передач, но водитель может ограничивать ее работу диапазоном передач или напрямую указать желаемую передачу для движения. При этом автоматика постарается выполнить команду водителя, но не даст коробке работать в недопустимых для нее условиях.
Так и в случае нашего балансировщика, вы можете задать желаемый «вес» сервера в диапазоне от 1 до 256, что позволит повлиять на нервномерное распределение нагрузки в условиях работы автоматического алгоритма.
Эй, ты там живой?
Работа балансировщика нагрузки непрерывно связана с процессом проверки доступности серверов, на которые будет распределена нагрузка. В нашем случае есть следующие варианты:
Проверки гибко настраиваются по нескольким параметрам, таким как:
- интервалы проверки;
- таймауты соединения;
- для HTTP-запросов — URL и ожидаемые коды ответа;
- пороговые значения успешных и неуспешных запросов подряд.
Прекрасные таймауты
В схеме работы Входящий запрос — Балансировщик — Сервер важно определить доступные временные рамки для выполнения запроса. Именно эти рамки и называются таймаутами. В нашем случае можно контролировать как таймаут между входящими запросами и балансировщиком нагрузки, так и таймаут между балансировщиком нагрузки и подконтрольными серверами.
Задав предельное значение таймаута, можно избежать возникновения большого количества «зависших» сессий. На место таких сессий смогут подключиться реальные пользователи, а ресурс количества соединений не будет расходоваться зря. Важно подобрать правильное значение, учитывая то, что клиенты используют разные интернет-каналы и не всегда они являются скоростными.
Сценарии использования
Мы детально рассмотрели в нашей Базе Знаний использование Балансировщика нагрузки для равномерного распределения запросов между разными серверами. Теперь расскажем о том, в каких сценариях можно его применять.
kb.selectel.ru/47683265.html
Масштабирование
Горизонтальное и вертикальное масштабирование без даунтайма — всегда актуально. Облачная платформа Selectel позволяет легко произвести оба вида масштабирования, но для того, чтобы не было перерывов в обслуживании как раз подойдет Балансировщик нагрузки.
При вертикальном масштабировании можно временно перенаправить клиентские запросы на другие виртуальные серверы и выполнить увеличение количества ресурсов на целевом сервере, а затем включить его в работу. После этого он сможет обслуживать большее количество клиентов.
Горизонтальное масштабирование также не вызывает никаких проблем. Создали необходимое количество виртуальных серверов и включили их в работу балансировщика нагрузки — вот и все. Теперь запросы клиентов стали обслуживаться большим количеством серверов, общая нагрузка на каждый сервер снизилась.
Отказоустойчивость
Мы уже не раз рассказывали о том, что такое High Availability и для чего используется. Процесс балансировки нагрузки как раз подразумевает отказоустойчивость в плане обслуживания запросов клиентов. Как только балансировщик «понимает», что подконтрольный ему сервер не может более отвечать на запросы (ну к примеру, он перегружен), то трафик переводится на другие серверы.
Помимо обычного режима работы, подконтрольному серверу можно назначить роль резервного. То есть, пока остальные серверы в рамках созданного правила работают, он находится в режиме ожидания. Как только они выходят из строя и перестают обрабатывать запросы — сервер выходит из ожидания и забирает нагрузку на себя.
Развертывание приложений
В работе DevOps большую популярность имеет техника развертывания приложений, под названием «канареечный релиз». Такое забавное название берет свое начало из работы шахтеров. Основную опасность при работе в шахте представляет метан, бесцветный газ без вкуса и запаха. Сам по себе он не токсичен, однако его опасность очевидна. Чтобы произошел взрыв, достаточно даже небольшой концентрации от 5% до 16%.
Поскольку почувствовать присутствие в воздухе метана человеку невозможно, шахтеры брали с собой клетки с канарейками. Пока птица жива и раздаются ее трели — можно безопасно работать. Если птица внезапно умолкла и скончалась — пора срочно выбираться на поверхность.
Процесс развертывания новых версий приложения чем-то схож с метаном. Баг может никак себя не проявлять, а затем внезапно вызвать очень серьезные проблемы, вплоть до остановки сервиса. Поэтому при развертывании один из серверов можно использовать в качестве «канарейки» и с помощью балансировщика нагрузки направить на него небольшую часть трафика. Чтобы трафик пользователей, попавший на «канареечный сервер», не уходил на другие серверы, используется уже описанный выше механизм Sticky sessions.
Если весь функционал приложения корректно заработал на «канареечном сервере», то можно продолжать его развертывание и на остальные серверы. Если же вдруг возникли проблемы — трафик переключается на работающие серверы со старой версией приложения с помощью того же самого балансировщика нагрузки.
Заключение
Распределение нагрузки на серверы — задача крайне важная, поскольку ее решение позволяет эффективно утилизировать ресурсы, а следовательно, экономить средства. Помимо этой задачи наш балансировщик нагрузки позволяет снижать потенциальные риски остановки сервиса при обновлениях приложений, а также обеспечивать отказоустойчивость виртуальной инфраструктуры.