Балансировщик HAProxy

  • Михаил
  • 12 мин. на прочтение
  • 144
  • 20 Jun 2022
  • 20 Jun 2022

Это первая статья из цикла про HAProxy. Здесь я затрону базовые понятия и уровни распределения запросов.

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

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

Что такое HAProxy и почему он подойдет

HAProxy — это балансировщик нагрузки, который умеет распределять и проксировать запросы по TCP и HTTP протоколу. Преимуществ у него немало:

  1. Он бесплатный.
  2. Он легкий и шустрый, способен обрабатывать 20 тысяч запросов в секунду, а то и больше.
  3. Он хорош для http-трафика.
  4. Его несложно вклинить в уже работающий проект.
  5. У него простая конфигурация и поэтому его можно быстро настроить под свои нужды.

Еще HAProxy использует Airbnb, Alibaba, Github, Instagram, Vimeo и еще не менее сорока известных высоконагруженных проектов. Так что причины его использовать весьма основательны.

 

Подробнее о том, чем Хапрокси является и не является в официальной документации

 

Базовые понятия конфигурации

Настройка HAProxy обычно сосредоточена вокруг пяти разделов: global, defaults, frontend, backend, реже listen.

Раздел global определяет общую конфигурацию для всего HAProxy

Defaults определяет настройки по-умолчанию для остальных разделов проксирования.

Раздел listen объединяет в себе описание для фронтенда и бэкенда и содержит полный список прокси. Он полезен для TCP трафика.

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

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

Разделы global, defaults и listen я затрагивать в статье почти не буду, поэтому просто дам стандартную конфигурацию из панели D2C, которую достаточно взять и применить:

global
 log 127.0.0.1 local0
 log 127.0.0.1 local1 notice
 maxconn 4096
 tune.ssl.default-dh-param 2048

defaults
 log global
 mode http
 option httplog
 option dontlognull
 option http-server-close
 option http-pretend-keepalive
 option forwardfor
 option originalto
 retries 3
 option redispatch
 maxconn 2000
 timeout connect 5000
 timeout client 50000
 timeout server 50000
 default-server init-addr last,libc,none

А вот на разделах Frontend и Backend я остановлюсь подробнее. Они помогут нам настроить балансировщик исходя из наших задач. 

 

 

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

Фронтенд обычно отвечает за тип распределения нагрузки и выбор бэкенда исходя из правил списков контроля доступа (ACL). 

Транспортный уровень или Layer 4

Самый простой способ распределения нагрузки — транспортный или Layer 4. В этом случае HAProxy будет выбирать Бэкенд в зависимости от порта, на который поступил запрос. Например, если запрос поступил на http://ваш-сайт.ру, то трафик обработает Бэкенд, отвечающий за 80 порт.

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

frontend haproxy
  mode tcp
  bind *:80
  default_backend http-backend

  • mode. Тип распределения нагрузки. В данном случае мы используем транспортный, поэтому указан протокол TCP. Если указать http, HAProxy станет работать на прикладном уровне (Layer 7).
  • bind. IP Адрес и порт, которые HAProxy должен слушать «на входе».
  • default_backend. Название конфигурации группы серверов, к которым надо направить запрос для обработки. В данном случае запросы пойдут к backend с названием http-backend.

На Бэкенде так же придется прописать mode tcp. В случае с транспортным уровнем конфигурация бэкенда может выглядеть так:

backend web_server_tcp
  mode tcp
  balance roundrobin
    server srv1 luna-1:80 check
    server srv2 luna-2:80 check

В HAProxy в одном конфигурационном файле допустимо использовать несколько типов распределения нагрузки. Например, можно для 80 порта задать режим http и распределять нагрузку на 7 уровне, а для 443 задать TCP и перенаправлять запросы на 4 уровне.

 

 

Такая функциональность будет полезна при работе с SSL: можно переадресовать запросы с 80 порта на 443:

frontend http_frontend *:80
  mode http
  redirect scheme https code 301 if !{ ssl_fc }

потом на транспортном уровне передать обработку запросов дальше:

frontend https_frontend_ssl_pass
  mode tcp
  bind *:443
  default_backend https-backend

и тогда уже сервера на бэкенде будут разбираться с SSL, а не HAProxy 🙂

 

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

 

 

Прикладной уровень или Layer 7

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

Распределение нагрузки на прикладном уровне пригодится, если, например, один сайт состоит из разных веб-приложений.

Покажу на примере. Допустим, для блога используется WordPress, на сайте самописный движок на php, а личный кабинет требует Node-js для фронтенда. И все это обслуживают разные команды разработчиков, которые работают в нескольких git репозиториях.

При таком раскладе вы бы точно захотели разъединить все это физически. В этом помогут списки контроля доступа (ACL). Чтобы решить задачу, распределим трафик в завимости от пути на сайте:

  • если запрос идет к основному сайту http://ваш-сайт.ру, будем отправлять на Бэкенд №1 к NGINX, который отдает страницы промосайта;
  • при обращении к блогу по адресу /blog на Бэкенд №2 к Варнишам, которые кэшируют наш Блог;
  • при обращении к кабинету /cabinet на Бэкенд №3 с Nodejs.

 

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

 

 

Так схема выглядит в конфигурации фронтенда:

frontend http bind *:80 mode http acl url_blog path_beg /blog use_backend backend-2 if url_blog acl url_cabinet path_beg /cabinet use_backend backend-3 if url_cabinet default_backend backend-1

  • mode http сообщает о том, чтобы HAProxy работал на уровне 7 по http-протоколу;
  • инструкция acl url_blog path_beg /blog создает правило url_blog, которое будет срабатвать при обращении по этому адресу;
  • инструкция use_backend backend-2 if url_blog сообщает, что если срабатывает правило url_blog, надо отправлять запросы к списку серверов на backend-2;
  • default_backend backend-1 говорит о том, что по умолчанию отправлять всех к списку серверов на backend-1, если ни одно правило не сработало.

На бэкенде мы так же пропишем mode http: 

backend web_server_tcp
  mode http
  balance roundrobin
    server srv1 luna-1:80 check
    server srv2 luna-2:80 check

 

 

На этом всё, в следующей статье цикла расскажу про секцию Backend и разные алгоритмы балансировки.

Запомнить

  • HAProxy — это быстрый бесплатный TCP/HTTP балансировщик нагрузки

Настройка HAProxy обычно сосредоточена вокруг пяти разделов: global, defaults, frontend, backend, реже listen. При этом первые 2 задают общие параметры по-умолчанию, а основная настройка происходит в последних трёх секциях.

  • HAProxy умеет работать на транспортном (Layer 4) и прикладном (Layer 7).
  • Чтобы распределять нагрузку на транспортном уровне нужно прописать mode tcp, на прикладном — mode http
  • В HAProxy в одном конфигурационном файле допустимо использовать несколько типов распределения запросов
  • Чтобы настроить гибкие правила распределения, нужно в секции Frontend прописать правила для списков управления доступом (ACL)