Введение в HAProxy и принципы распределения нагрузки

HAProxy (High Availability Proxy) — популярный прокси сервер для Linux, Solaris и FreeBSD с возможностью балансировки нагрузки TCP/HTTP с открытым программным кодом. Его основная задача — повышение производительности серверной среды путем распределения рабочей нагрузки среди нескольких серверов (web, приложения, базы данных). Им пользуются такие известные проекты как GitHub, Imgur, Instagram и Twitter.

Терминология HAProxy

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

Список контроля доступа (ACL)

Когда мы разговариваем о распределении нагрузки, ACL применяется для проверки установленных правил распределения и для запуска некоторого действия (например, выбор сервера или блокировка сетевого запроса) в зависимости от применимости правила.

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

Пример ACL:

acl url_blog pat_beg /blog

Это правило будет применено в случае, если путь, к которому обращается пользователь начинается с /blog. То есть следующий запрос попадает под действие правила: http://yourdomain.com/blog/blog-entry-1.

Для более подробного описания использования ACL обращайтесь к инструкции по настройке HAProxy.

Backend

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

  • алгоритм распределения нагрузки
  • набор серверов и портов

Бекэнд может включать в себя как один, так и несколько серверов. Другими словами, добавляя больше серверов вы увеличиваете максимально возможную нагрузку, распределяя её по всем серверам. Так же, таким образом, повышается отказоустойчивость в случае, если отказал один из серверов.

Приведем пример настройки двух бекэндов, web-backend и blog-backend обрабатывающих запросы? поступающие на 80 порт:

backend web-backend
  balance roundrobin
  server web1 web1.yourdomain.com:80 check
  server web2 web2.yourdomain.com:80 check
backend blog-backend
  balance roundrobin
  mode http
  server blog1 blog1.yourdomain.com:80 check
  server blog1 blog1.yourdomain.com:80 check

Строка balance roundrobin указывает на алгоритм балансировки, который описан в секции Алгоритмы распределения нагрузки ниже.

Mode http указывает на то, что будет использован 7 слой прокси, который также описан в Типы распределения нагрузки.

Параметр check означает, что эти серверы должны проверяться на работоспособность.

Frontend

Фронтэнд определяет каким образом запросы должны быть перенаправлены на бекэнд. Они указываются в разделе frontend настройки HAProxy. Их определение состоит из следующих частей:

  • набор ip адресов и портов
  • ACL
  • правила use_backend, указывающие на то, какой бекэнд должен быть задействован в зависимости от соответствия правилам ACL, а также и/или default_backend — бекэнд, используемый во всех остальных случаях.

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

Типы распределения нагрузки

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

Отсутствие нагрузки

Самое простое web-приложение без распределения нагрузки обычно выглядит следующим образом:

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

Распределение нагрузки 4 уровня

Самый простой способ балансировки нагрузки на сервер — это использование распределения 4 уровня (транспортного уровня). При нём распределение происходит исходя из диапазона IP адресов и порта (например, если запрос поступил на http://yourdomain.com/anything, то трафик будет обработан бекэндом, отвечающим за работу с 80 портом на этом домене).

Приведем диаграмму простого примера применения балансировки 4 уровня:

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

Распределение нагрузки 7 уровня

Следующий, более сложный, способ — балансировка нагрузки 7 уровня (уровень приложения). Такой способ позволяет управлять потоком трафика в зависимости от содержания запроса. Так же он допускает выполнение нескольких веб-приложений на одном домене и порте.

Приведем диаграмму простого примера применения балансировки 7 уровня:

В этом случае, если пользователь обратился к yourdomain.com/blog, то он перенаправляется на бекэнд, отвечающий за blog, то есть к серверам, работающим с блогом приложения. Все остальные запросы направляются на web-backend, который уже использует совсем другое приложение. В данном примере оба бекэнда используют один сервер базы данных.

Пример настройки фронтэнда обычно выглядит следующим образом:

frontend http
 bind *:80
 mode http
 acl url_blog path_beg /blog
 use_backend blog-backend if url_blog
 default_backend web-backend

Данная настройка определяет фронтэнд по имени http, который отвечает за весь входящий трафик 80 порта.

acl url_blog path_beg /blog указывает шаблон адреса запроса. Этому правилу соответствуют все запросы начинающиеся с /blog.

use_backend blog-backend if url_blog перенаправляет трафик в соотетствии с правилами ACL.

default_backend web-backend указывает на то, что весь трафик будет перенаправлен на web-backend.

Алгоритмы распределения нагрузки

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

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

Приведем основные алгоритмы:

roundrobin

Алгоритм, применяемый по умолчанию. Перебирает сервера по очереди.

leastconn

Выбирает сервер с наименьшим числом активных соединений. Рекомендуется к использованию для длинных сессий. Сервера в одном бекэнде варьируются циклически.

source

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

Продолжительные сессии

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

Проверка работоспособности

HAProxy применяет проверку работоспособности сервера, чтобы определить способен ли он обработать запрос. Так нам не приходится вручную исключать сервер из настройки бекэнда. По умолчанию HAProxy пытается установить TCP соединение с сервером и проверяет производит ли тот обработку данных поступающих на 80 порт.

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

Для некоторых же видов серверов, как, например, сервера баз данных, такой проверки недостаточно.

Другие решения

Если HAProxy показался вам слишком сложным для решения ваших проблем, попробуйте рассмотреть следующие варианты:

  • Linux Virtual Servers (LVS) — просто балансировщик 4 уровня, включенный в большинство Linux дистрибутивов.
  • Nginx — быстрый и надежный веб сервер, который так же можно использовать в качестве балансировщика. Он очень часто используется в связке с HAProxy благодаря своим возможностям кеширования и архивирования.

Заключение

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