Содержание
В этой статье мы попробуем разобраться в том, что же такое HAProxy, а также рассмотреть его возможности и преимущества. Прежде всего, договоримся о понятиях. HAProxy — это серверное ПО, целью которого является обеспечение высокой доступности и балансировки нагрузки для TCP и HTTP-приложений, благодаря распределению входящих запросов на несколько обслуживающих серверов.
HAProxy активно используется в различных высоконагруженных веб-сайтах, таких как Instagram, Twitter, Reddit и т.д. К числу его основных функций можно отнести:
- Балансировка HTTP и TCP соединений
- Возможность перезапуска без потери активных соединений
- Встроенный веб-интерфейс для просмотра статистики с HTTP basic аутентификацией
- Возможность терминировать SSL (можно ставить перед веб-приложениями вместо nginx)
Балансировка HTTP и TCP соединений
HAProxy поддерживает балансировку, как HTTP/HTTPS/HTTP2 (например, веб-серверы или Elasticsearch), так и TCP соединений (например, postgres или redis). Поддерживаются разные алгоритмы балансировки запросов. Из наиболее важных можно выделить:
— roundrobin: запросы отправляются к бэкендам по очереди. Это крайне удобно для балансировки stateless протоколов, вроде HTTP. Однако если в приложениях есть данные, которые хранятся не в разделяемом хранилище, а на конкретном бэкенде (например, сессии или загруженные файлы), этот метод не подходит.
— leastconn: запрос отправляется к бекенду с наименьшим количеством открытых соединений.
— source: запросы с одного IP всегда отправляются на один и тот же бэкенд. Может быть полезным для таких сервисов, как memcached.
Существуют вариации и других алгоритмов, некоторые из них специфичны для HTTP. Они детально описаны в документации HAproxy.
Возможность перезапуска без потери активных соединений
HAProxy не поддерживает перечитывание конфига, но обладает функцией перезапуска без потери открытых соединений. Для этого запускается новый процесс, принимающий новые соединения. В то же время старый обслуживает старые соединения, завершаясь после закрытия старых соединений. Более детально данный механизм описан в 4 секции данной статьи.
Использование разных алгоритмов балансировки
Source-based балансировка
Часто, особенно для TCP бэкендов, возникает необходимость гарантировать что запросы от одного и того же клиента всегда пойдут на один и тот же бэкенд. Для этого применяется алгоритм балансировки «source». Таким образом можно распределить нагрузку между разными экземплярами memcached или redis (при условии, что все redis’ы независимы и не являются master/slave друг друга).
Допустим, нам необходимо обеспечить единую точку входа для memcached. Для клиентов это должно выглядеть, как один memcached сервер. При этом, если клиент сохранил данные в бэкенд X, то и запрос на чтение должен быть отправлен на бэкенд X.
Этого можно добиться следующим конфигом:
listen memcached *:11211
option tcplog
balance source # ip-based balancing
server memcached-1 host-1.example.com:11211 check inter 3s fall 3 minconn 50
server memcached-2 host-2.example.com:11211 check inter 3s fall 3 minconn 50
server memcached-3 host-3.example.com:11211 check inter 3s fall 3 minconn 50
Если все три бэкенда работают, запросы будут распределяться, именно таким образом. Если какой-то из них упадет, то HAProxy исключает его из пула и отправляет запросы на другой бэкенд. В результате клиент теряет кеш, однако сохраняет доступ к сервису.
Round-robin балансировка
Если нет разницы, какой именно бэкенд обслужит запрос, удобнее использовать round-robin алгоритм. Он позволяет при одинаковых весах бэкендов, распределять запросы циклично и равнозначно. Это можно применять для балансировки как чтения, так и записи в Elasticsearch, поскольку всю сложную работу по распределению записи кластер узлов Elasticsearch выполняет самостоятельно. Соответственно, конфиг будет выглядеть следующим образом:
listen *:9200
option tcplog
server elastic-1 host-1.example.com:9200 check inter 3s fall 3 minconn 50
server elastic-2 host-2.example.com:9200 check inter 3s fall 3 minconn 50
server elastic-3 host-3.example.com:9200 check inter 3s fall 3 minconn 50
Использование TCP-бекендов редисов в схеме master-slave
Вышеупомянутые примеры балансировки предполагали, что сервисы не зависят друг от друга. Однако в случае, если существует основной и резервный сервис, необходима более сложная конфигурация для того чтобы HAProxy мог определить, какой из сервисов является основным, то есть готовым принимать запросы.
В качестве примера можно рассмотреть несколько экземпляров redis, один из которых является мастером, а остальные — его репликами. Запросы от пользователя должны уходить только на мастер, поэтому необходимо, чтобы HAProxy понял, какой из бэкендов в любой момент времени является мастером.
По умолчанию для того чтобы понять — жив ли бэкенд, HAProxy использует простую проверку доступности порта. Помимо этого он поддерживает и сложные проверки. Они состоят из отсылки в указанный порт неких данных и проверки полученного ответа. Таким образом, HAProxy может общаться непосредственно с redis-демоном для получения его роли (master/slave). Вот один из примеров такой настройки.
Несмотря на то, что настройка является сравнительно простой и подходит для большинства случаев, она не обеспечивает 100% корректности определения мастера. Так как в случае с network split возможна ситуация, когда два разных redis’а будут считать себя мастером, что может ввести HAProxy в заблуждение. В таком случае, предпочтительно использовать redis sentinel в качестве источника. Дискуссию на эту тему и пример такого решения можно найти в комментариях к данной статье. Тем не менее, это значительно усложняет конфиг HAProxy.
В случае же, если вам нужно не просто слать все запросы в мастер, но и отправлять их на чтение на слейвы, лучше использовать специализированные решения (например, pgpool для postgres), а не HAProxy.
Особенности применения haproxy в docker-контейнере
Перезапуск без потери соединений
До версии 1.5.16 HAProxy запускался, как основной процесс в стандартном docker-контейнере (т.е. как PID 1). Это делало невозможным перезапуск без потери соединения. Так как при завершении PID 1 контейнер также завершался. Поэтому нам необходимо, чтобы таким процессом не был сам HAProxy. Начиная с haproxy: 1.5.16 в качестве PID 1 запускается haproxy-systemd-wrapper, который обеспечивает перезапуск HAProxy, но при этом остается живым. Дополнительный плюс — контейнер теперь нормально завершается, как по Ctrl+С, так и через docker stop.
Логирование
Ожидается, что приложения, запускаемые в docker-контейнерах, будут выводить все свои логи в stdout. В таком случае логи будут доступны через docker logs. HAProxy не поддерживает логирование в файл или stdout, только syslog. Существует способ получить логи, указав HAProxy. А дальше просто логировать в /dev/log. Для этого в конфиге haproxy указывается:
defaults
log /dev/log local0 debug
option dontlognull
option dontlog-normal
Внутрь контейнера монтируется /dev/log:
docker run haproxy -v /dev/log:/dev/log
При этом docker logs по-прежнему не будет работать. Но будет работать системный лог. В современных дистрибутивах до него можно добраться через journalctl.
Зачем использовать HAProxy?
Сегодня HAProxy не является единственным решением, предоставляющим проксирование и HTTP, и TCP. Например, c 2014 года nginx также поддерживает TCP-проксирование. Тем не менее, существуют причины, по которым, стоит отдать предпочтение именно HAProxy:
- Зрелость продукта. Первый релиз HAProxy состоялся в декабре 2001 года, с тех пор он активно развивается.
- Скорость работы. HAProxy написан на C и используется в высоконагруженных системах.
- Высокая настраиваемость. Документация очень обширна, настроить можно все.
- Надежность. HAProxy — пример такого продукта, который можно настроить и забыть, он просто будет работать.
- Широкий спектр применения. Reverse proxy, Load Balancing, Failover, поддержка HTTP и TCP, высокая настраиваемость — всё это позволяет использовать HAProxy во множестве сценариев.
- Встроенный веб-интерфейс со статистикой. Мелочь, но мелочь полезная.
- Мониторинг. Тот же веб-интерфейс может выводить данные не только как HTML-страницу, но и в CSV-формате, что позволяет интегрировать его с системами мониторинга.
Вывод
Наши поздравления! Вы ознакомились с основными понятиями HAProxy и балансировки нагрузки. В мире современной веб-разработки они очень и очень важны.
HAProxy — один из самых популярных открытых балансировщиков нагрузки TCP/HTTP с открытым программным кодом. И одновременно — прокси сервер для таких систем, как Linux, FreeBSD и Solaris. Чем же он вам пригодится? Прежде всего, вы сможете в значительной степени улучшить производительность и ошибкоустойчивость серверного окружения при помощи распределения рабочей нагрузки между несколькими серверами. Впечатляет, не правда ли? Итак, если вы еще не уверены в HAProxy, мы идем к вам!