HAProxy
HAProxy (High Availability Proxy) — это высокопроизводительный, отказоустойчивый прокси-сервер и балансировщик нагрузки, способный работать как с HTTP(S), так и с TCP-трафиком. Это делает его идеальным решением не только для веб-приложений, но и для баз данных, почтовых систем, брокеров сообщений и других сервисов.
HAProxy позволяет:
- увеличить доступность (если один сервер «падает», трафик уходит на другие),
- масштабировать нагрузку при росте числа пользователей,
- гибко управлять маршрутизацией запросов.
Балансировщик нагрузки принимает входящий сетевой трафик от клиента и, основываясь на некоторых критериях этого трафика, отправляет эти сообщения на один из нескольких бэкенд-серверов
config
Конфигурационный файл обычно располагается по следующему пути: /etc/haproxy/haproxy.cfg и делится на секции:
- global – общие параметры (логи, количество процессов и пр.).
- defaults – настройки по умолчанию для всех фронтендов и бэкендов.
-
frontend – «лицо» балансировщика, куда приходит трафик от клиентов.
Frontend определяет IP-адреса и порты, к которым могут подключаться клиенты, то есть, по сути, определяет внешний интерфейс подключения и состоит из следующих компонентов:
- набор IP-адресов и порт (например, 172.16.35.12:80, *:443 и т.д);
- ACL-правила
use_backend, которые определяют, какие бэкенды использовать в зависимости от условий ACL; - правило
default_backend, которое обрабатывает все остальные случаи.
-
backend – список серверов, на которые распределяется трафик.
В базовом варианте бэкенд определяется следующим образом:
- выбор алгоритма балансировки;
- список серверов и портов.
Бэкенд может содержать в себе один или несколько серверов. И в общем случае, это и является прямым назначением HAProxy — добавление большего количества серверов, для того чтобы увеличить потенциальную емкость нагрузки путем распределения ее на несколько серверов. Плюс таким же образом достигается повышение надежности на случай, если некоторые из внутренних серверов станут недоступными.
Простой пример HTTP-балансировки между двумя срверами:
global
log /dev/log local0
log /dev/log local1 notice
daemon
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
frontend http_front
bind *:80
default_backend http_back
backend http_back
balance roundrobin
server web1 192.168.1.10:80 check
server web2 192.168.1.11:80 check
Алгоритмы балансировки нагрузки
Используемый алгоритм балансировки нагрузки определяет, какой сервер в бэкенде будет выбран при балансировке нагрузки. HAProxy предлагает несколько вариантов алгоритмов, причем в дополнение к алгоритму распределения нагрузки серверам может быть назначен весовой параметр для управления частотой выбора сервера относительно других. HAProxy предоставляет достаточно tбольшое количество алгоритмовt, вот лиш некоторые из них:
- roundrobin — алгоритм, который выбирает серверы по очереди, является алгоритмом по умолчанию..
- leastconn – отправляет запросы на сервер с наименьшим числом активных соединений.
- source – этот алгоритм выбирает, какой сервер использовать, основываясь на хеш-адресе исходного IP-адреса, то есть IP-адреса пользователя, это один из способов гарантировать, что пользователь будет подключаться к одному и тому же серверу.
- uri/hdr/cookie – балансировка на основе URI, заголовков или cookies.
stats
HAProxy умеет показывать удобную веб-страницу с текущими метриками.
Страница статистики будет доступна по адресу: http://<haproxy-host>:8080/stats.
logging
Логи по умолчанию идут в rsyslog: /var/log/haproxy.log
health check
HAProxy использует проверку работоспособности, чтобы определить, доступен ли внутренний сервер для обработки запросов. Это позволяет избежать необходимости вручную удалять сервер из конфигурации, если он становится недоступным. Проверка работоспособности по умолчанию заключается в попытке установить TCP-соединение с сервером, т.е. происходит проверка, прослушивает ли внутренний сервер заданные IP-адрес и порт. Если сервер не проходит проверку работоспособности и, следовательно, не может обслуживать запросы, то он автоматически отключается в бэкенде, и трафик не будет перенаправляться на него, пока он снова не станет работоспособным. Если же все серверы в бэкенде выйдут из строя, то приложение или сервис станет недоступно, пока хотя бы один из этих бэкенд-серверов снова не станет работоспособным.
server web1 192.168.1.20:80 check inter 5s rise 2 fall 3
# inter 5s — проверка каждые 5 секунд.
# rise 2 — сервер считается «здоровым», если успешно ответил 2 раза подряд.
# fall 3 — считается «павшим» после 3 неудачных проверок.
routing
L4-routing
Layer 4 (TCP) — прозрачная проксификация на уровне транспортного протокола: полезно для баз данных, SMTP, любых TCP-служб.
L4-routing - это просто и быстро, работает на транспортном уровне, внутрь пакета не смотрит, поэтому экономичный по ресурсам. Кофигурируется тоже просто: во frontend указывается порт, который нужно слушать; в backend список серверов, куда пересылается трафик.
frontend postgresql
mode tcp
bind :5432
default_backend postgresql_servers
backend postgresql_servers
mode tcp
balance leastconn
server sql1 192.168.0.10:3306
server sql2 192.168.0.11:3306
Такой режим практически не нагружает процессор, позволяет обрабатывать десятки тысяч соединений и подходит для сервисов, где не требуется анализ содержимого запросов.
L7-routing
- Layer 7 (HTTP) — работа с HTTP-заголовками, возможность роутинга по URI, доменам, cookies.
L7-routing - это умная и дорогая маршрутизация, каждый пакет анализируется на основе ACL-правил и перенаправляется на соответствующий сервер.
frontend http_front
bind *:80
# ACL №1 — путь /api
acl is_api path_beg /api
# ACL №2 — путь /admin
acl is_admin path_beg /admin
# ACL №3 — отдача статики
acl is_static path_end .css .js .png .jpg
# Маршрутизация
use_backend api_servers if is_api
use_backend admin_servers if is_admin
use_backend static_servers if is_static
# Backend по умолчанию
default_backend default_servers
backend api_servers
balance roundrobin
server api1 10.0.0.11:8080 check
server api2 10.0.0.12:8080 check
backend admin_servers
balance roundrobin
server admin1 10.0.0.21:8080 check
backend static_servers
balance roundrobin
server static1 10.0.0.31:80 check
server static2 10.0.0.32:80 check
backend default_servers
balance roundrobin
server web1 10.0.0.41:80 check
Такой подход требует больше CPU и памяти из-за разбора протокола, но даёт максимальную гибкость в управлении трафиком и позволяет реализовывать сложные схемы маршрутизации.
ACL
ACL (Access Control List) — это универсальный инструмент, позволяющий описывать условия обработки запросов на основе различных признаков: IP-адреса клиента, пути и параметров URL, HTTP-заголовков, методов, доменов SNI, а также регулярных выражений и масок. По сути, ACL — это условие if в конфигурации HAProxy: оно вычисляется для каждого запроса, и в зависимости от результата (true/false) выбирается нужное действие — перенаправить, заблокировать, модифицировать или отправить в определённый backend. Благодаря ACL конфигурация перестаёт быть статичной и превращается в набор динамических правил, реагирующих на контекст запроса. Это особенно важно для маршрутизации (routing), когда от характеристик запроса зависит выбор целевого сервиса.
Порядок ACL имеет значение - правила проверяются сверху вниз
Sticky sessions
Привязка клиента к серверу, если веб-приложению нужна «сессия» на одном бэкенде (например, хранение корзины в памяти), добавляют cookie:
backend http_back
balance roundrobin
cookie SERVERID insert indirect nocache
server web1 192.168.1.10:80 check cookie s1
server web2 192.168.1.11:80 check cookie s2
timeouts
В конфигурации HAProxy директивы timeout используются для определения различных предельных временных интервалов, влияющих на установление соединений, передачу запросов и откликов, а также поведение keep-alive-соединений. Все таймауты задаются в секундах, миллисекундах или комбинированном формате (10s, 500ms, 1m), и их можно указывать как в секции defaults, так и в секциях frontend или backend — приоритет отдается более локальной настройке. Таймауты — очень важные настройки. Они помогают избежать долгих висящих TCP-соединений, которые могут занимать дескрипторы, и позволяют использовать эти ресурсы для других соединений.
- timeout connect. Время на установку TCP-соединения с backend-сервером. Если backend не отвечает → сервер считается недоступным.
timeout connect 5s - timeout client. Максимальное время бездействия клиента.
timeout client 30s - timeout server. Максимальное время бездействия backend-сервера. Если backend не отвечает или завис, соединение завершится по истечении заданного времени.
timeout server 30s - timeout http-request. Время ожидания полного HTTP запроса (headers).
timeout http-request 10s - timeout http-keep-alive. Idle время между HTTP запросами на одном соединении.
timeout http-keep-alive 10s - timeout queue. Сколько запрос может ждать свободный backend. Если backend перегружен → запрос падает.
timeout queue 30s - timeout retry. Пауза между попытками соединения.
timeout retry 3s - timeout tunnel. Очень важный для: WebSocket, gRPC, SSH proxy, VPN, long connections. Если не указать → соединения будут рваться.
timeout tunnel 1h - timeout tarpit — время ожидания при использовании механизма tarpitting (например, при блокировке клиентов). Это может применяться для создания искусственной задержки на подозрительных запросах.
timeout tarpit 10s - timeout check. Таймаут health-check проверки backend-сервера.
timeout check 5s
```cfg title="Пример production defaults defaults timeout connect 500ms timeout client 30s timeout server 30s timeout http-request 3s timeout http-keep-alive 10s timeout queue 10s timeout tarpit 10s timeout tunnel 30m timeout client-fin 10s timeout server-fin 10s timeout check 3s
> HAProxy НЕ любит отсутствующие таймауты. Если не указать → warning: `missing timeouts for backend`. И могут появиться висящие соединения.
```text title="Как посмотреть причины таймаута"
Логи HAProxy содержат termination flags:
sC → server timeout
cC → client timeout
SC → server connection error
PR → proxy reject