Балансировка нагрузки в веб‑сервисах решает сразу две задачи: масштабирование и отказоустойчивость. В этой статье поговорим о возможностях балансировки нагрузки для HTTP(S) протокола в Angie.

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

Навигация по циклу

  1. Почему стоит переходить на Angie.

  2. Установка Angie из пакетов и в докере.

  3. Переезд с Nginx на Angie. Пошаговая инструкция.

  4. Настройка location в Angie. Разделение динамических и статических запросов.

  5. Перенаправления в Angie: return, rewrite и примеры их применения.

  6. Сжатие текста в Angie: статика, динамика, производительность.

  7. Серверное кэширование в Angie: тонкости настройки.

  8. Настройка TLS в Angie: безопасность и скорость.

  9. Настройка Angie в роли обратного HTTP-прокси.

  10. Балансировка нагрузки для HTTP(S) в Angie.

  11. Мониторинг Angie с помощью Console Light и API.

  12. Балансировка и проксирование L4-трафика в Angie.

  13. Клиентское кэширование в Angie.

  14. Динамические группы проксируемых серверов в Angie.

  15. Мониторинг Angie с Prometheus и Grafana.

  16. Отказоустойчивый кластер Angie с VRRP и Keepalived.

  17. Контроль доступа в Angie.

  18. Аутентификация клиентов в Angie с помощью TLS-сертификатов.

Видеоверсия

Для вашего удобства подготовлена видеоверсия этой статьи, доступна на Rutube, VKVideo и YouTube.

Базовая конфигурация балансировки в Angie

При настройке балансировки в Angie всё начинается с блока upstream одноимённого модуля. Для балансировки HTTP(S)‑приложений блок должен быть объявлен в контексте http. Удобно указывать upstream до блока server, который его использует.

http {
  upstream backend {
    zone upstream-backend 10m;
    server 127.0.0.1:9000;
    server 127.0.0.1:9001;
  }
  server {
    listen 80;
	location / {
		proxy_pass http://backend;
	}
  }
}

Посмотрим, что мы настроили в конфиге выше. Блок upstream определяет группу серверов, которые будут объединены названием backend, это же название мы используем в директиве proxy_pass в основном сервере. Для группы серверов добавлена зона разделяемой памяти для хранения состояния серверов и их настроек, также она даёт возможность мониторинга с помощью API и Angie Console Light.

Так как мы не указали никаких дополнительных директив, балансировка осуществляется методом round‑robin, то есть последовательным перебором серверов. При этом каждый сервер будет получать одинаковое количество запросов. В случае недоступности одного из серверов, запрос будет направлен на другой сервер, более точно поведение в случае ошибок можно настроить с помощью параметров директив server и proxy_next_upstream.

Наблюдать статусы серверов в группах очень удобно в штатной консоли мониторинга Angie Console Light, благодаря настройке директивы zone.

Статусы апстримов в Angie Console Light
Статусы апстримов �� Angie Console Light

На этом настройка балансировки формально завершена. Дальше будем разбираться с подробностями конфигурации.

Алгоритмы балансировки

В простейшем варианте, без указания дополнительных директив мы получили алгоритм балансировки round‑robin. Кроме того, в открытой версии Angie доступны методы (директива):

  • Least connections (least_conn);

  • IP hash (ip_hash);

  • Hash (hash);

  • Random (random);

  • Random least connection (random two).

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

upstream backend {
  zone upstream-backend 10m;
  least_conn;
  server 127.0.0.1:9000;
  server 127.0.0.1:9001;
}

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

Метод hash имеет параметр в виде набора переменных для получения хэша, а также параметр для консистентного хеширования (consistent). Пример конфигурации с определением сервера по URI запроса будет выглядеть так.

upstream backend {
  zone upstream-backend 10m;
  hash $request_uri consistent;
  server 127.0.0.1:9000;
  server 127.0.0.1:9001;
}

Использование консистентного хэширования позволит минимизировать миграцию клиентов по серверам в случае добавления или удаления серверов в группе.

Если в архитектуре приложения используются несколько балансировщиков Angie, использующие одни и те же бэкенд серверы, то целесообразно использовать метод балансировки random. Этот метод предполагает произвольный выбор сервера, что даёт возможность более равномерной балансировки в условиях неопределенности из‑за нескольких балансировщиков. Дополнительно можно добавить параметр two, который поменяет поведение: выбираются два произвольных сервера и между ними тот, который имеет минимальное количество активных соединений (least connections). Настроить метод random two least connections несложно:

upstream backend {
  zone upstream-backend 10m;
  random two;
  server 127.0.0.1:9000;
  server 127.0.0.1:9001;
}

Помимо рассмотренных методов балансировки в Angie доступна функциональность привязки клиента к выбранному серверу на основании данных запроса. Посмотрим, как настроить эту привязку.

Режим sticky

Всего в Angie существуют четыре режима привязки сессии клиента к бэкенд‑серверу, первые два до��тупны в OSS‑версии, а остальные — в PRO:

  • sticky cookie;

  • sticky route;

  • sticky learn (PRO);

  • sticky learn с remote action (PRO).

Режим sticky cookie использует cookie для хранения информации о сервере. Если cookie отсутствует в запросе, Angie установит его для клиента. Достаточно указать название cookie и назначить (опционально) параметры sid для каждого сервера. По умолчанию sid будет равен MD5-хэшу адреса и порта сервера. Дополнительно для защиты DoS-атак в режимах cookie или route можно добавить соль и хеширование значения через директиву sticky_secret, тогда значения cookie будет таким:

echo -n "<sid><sticky_secret>" | md5sum

Для cookie также доступно назначение атрибутов. Полная конфигурация режима sticky cookie с использованием sticky_secret показана ниже.

upstream backend {
  	zone upstream-backend 10m;
   	server 127.0.0.1:9000 sid=one;
    server 127.0.0.1:9001 sid=two;
    sticky cookie serv_cook max-age=600;
	sticky_secret sectdss.$remote_addr;
}

Здесь будет использоваться cookie с именем serv_cook, время жизни 600 секунд. В значение будет добавляться соль с участием переменной и результирующая строка захэширована.

Режим sticky route основан на использовании уже установленных проксируемым сервером параметрах запроса, которые можно получить через переменные в Angie. Это может быть GET‑параметр запроса, значение cookie или заголовка запроса. Например, настроим выбор сервера в зависимости от параметра запроса route (использование открытого параметра без sticky_secret может быть опасно с точки зрения уязвимости к DoS‑атакам).

upstream backend {
   	zone upstream-backend 10m;
   	server 127.0.0.1:9000 sid=one;
    server 127.0.0.1:9001 sid=two;
    sticky route $arg_route;
}

Для проверки выбора сервера можно отправлять запросы вида:

curl http://localhost/?route=one
curl http://localhost/?route=two

Рассмотренные выше варианты балансировки в режиме sticky позволяют Angie выбрать другой сервер, если привязанный к сессии недоступен. Эту возможность можно отключить, добавив директиву sticky_strict on. Тогда при недоступности привязанного сервера клиент получит ошибку 502.

Итак, мы рассмотрели несколько различных методов балансировки, а также режим sticky, но не меняли параметры самих серверов в блоке upstream, поэтому настало время изучить директиву server подробнее. 

Параметры директивы server

У каждого сервера можно указать ряд параметров в директиве server (не путать с блоком server). Не все параметры доступны для любых режимов балансировки, перечислим их назначение:

  • weight – вес сервера;

  • max_conns – максимальное количество одновременных подключений;

  • backup – запасной сервер;

  • down – недоступный сервер;

  • max_fails – максимальное количество ошибок;

  • fail_timeout – время для определения недоступности сервера (max_fails);

  • resolve — разрешать имя сервера (не только при запуске);

  • slow_start — плавный ввод сервера в работу;

  • drain — плавный вывод сервера из балансировки.

Вес сервера позволяет распределять нагрузку неравномерно, например для учета различной мощности серверов. Доля трафика на сервер будет равна весу с��рвера, делённому на сумму весов серверов.

Состояние сервера backup означает, что обращение к нему будет только в случае недоступности всех остальных серверов. При этом параметр down исключает запросы на сервер в любых случаях.

Два параметра max_fails и fail_timeout определяют соответственно количество ошибок и время для определения недоступности сервера при пассивных проверках. Также они используются при обратном вводе сервера в работу после сбоя.

Отдельно стоит сказать про resolve. Этот режим позволяет обновлять информацию о серверах из DNS. По умолчанию, доменные имена преобразуются в адреса при загрузке конфигурации (один раз). При установленном параметре resolve и директиве resolver Angie будет регулярно обновлять адреса. В таком случае получаем конфигурацию:

resolver 127.0.0.53 status_zone=resolver;
upstream backend {
  zone backend 1m;
  server test.backend:9000 resolve; 
}

Также resolve можно применять со специальными DNS-записями типа SRV, тогда нужно указать название сервиса:

server test.backend.ru service=http resolve;

Для работы этой конфигурации в DNS нужно создать SRV‑записи для хостов _http.tcp.test.backend.ru. Для SRV‑записей можно использовать приоритеты и веса, которые будут учитываться в Angie.

В случае, если возможностей OSS‑версии Angie недостаточно для ваших задач, можно обратиться к расширенному функционалу Angie PRO.

Возможности балансировки Angie PRO

Конечно, Angie PRO поддерживает все возможности открытой версии, а также дополнительные алгоритмы балансировки и режимы.

Перечислим алгоритмы в PRO‑версии:

  • Least Time — по времени ответа серверов;

  • Feedback — учёт произвольных параметров в качестве обратной связи от сервера.

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

Кроме того, есть дополнительные возможности, связанные балансировкой:

  • возможность динамического управления статусами серверов через API и Console Light;

  • режимы привязки сессий sticky learn и sticky learn с remote action — последний позволяет организовать централизованное хранение сессий;

  • активные проверки серверов (модуль upstream_probe);

  • переключение на группу резервных серверов (backup_switch);

  • хранение состояния серверов в файле (state);

  • поддержка очередей запросов к серверам (queue);

  • привязка клиентского соединения к серверному (bind_conn).

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

Итоги

В статье разобраны основные возможности Angie по балансировке трафика в режиме HTTP. Для самых востребованных конфигураций разобраны примеры настройки группы серверов и возможные варианты адаптации под запросы приложений. Как обычно, остальные детали настройки можно почерпнуть из документации.

Следующая статья цикла: Мониторинг Angie с помощью Console Light и API.