Алгоритмы балансировки нагрузки. Часть 1

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

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

Визуализация проблемы

Начнем с самого начала: один балансировщик нагрузки отправляет запросы на один сервер. Запросы отправляются со скоростью 1 запрос в секунду (RPS), и каждый запрос уменьшается в размере по мере того, как сервер его обрабатывает.

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

Здесь мы видим, что скорость в 3 RPS приводит к отбрасыванию некоторых запросов. Если запрос поступает на сервер в то время, когда другой запрос находится в обработке, сервер отбрасывает его. В результате пользователю будет показана ошибка, а этого необходимо избежать. Можно добавить еще один сервер к балансировщику нагрузки, чтобы решить эту проблему.

Больше никаких пропущенных запросов! То, как ведет себя балансировщик нагрузки, отправляя запрос на каждый сервер по очереди, называется «циклической» (round-robin) балансировкой нагрузки. Это одна из самых простых форм балансировки нагрузки, которая хорошо работает, когда все ваши серверы одинаково мощные, а запросы одинаково затратны по времени.

Когда «циклический» способ не подходит

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

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

Несмотря на то что большинство запросов успешно обрабатываются, некоторые из них не отбрасываются. Один из способов борьбы с этим — наличие «очереди запросов».

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

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

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

Однако, несмотря на свои недостатки, данный метод по-прежнему является методом балансировки нагрузки HTTP по умолчанию для nginx.

Совершенствуем Round-robin

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

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

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

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

В следующем примере на каждый сервер был добавлен текст, который показывает среднюю задержку последних 3 обработанных запросов. Затем решается, отправлять ли 1, 2 или 3 запроса на каждый сервер, основываясь на относительной разнице в задержках. Результат очень похож на первоначальное моделирование взвешенного round-robin, но здесь нет необходимости заранее указывать вес каждого сервера. Этот алгоритм также сможет адаптироваться к изменениям в производительности серверов с течением времени. Это называется «динамический взвешенный round-robin».

В следующей статье рассмотрим более эффективный метод балансировки нагрузки.


Источник: samwho.dev 

Условия передачи информации

Я даю согласие OOO «ЭсБилдер» (далее «BINN») на обработку моих персональных данных в соответствии со статьями 6, 9, 10, 18 Федерального закона от 27 июля 2006 года № 152-ФЗ «О персональных данных», указанных в онлайн-форме и/или предоставленных мною с целью:

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

Настоящее согласие применяется в отношении обработки следующих данных: имя, номер телефона, адрес электронной почты (E-mail).

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

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