Балансировка нагрузки#
Angie распределяет клиентские запросы по группе проксируемых серверов, описанной блоком upstream. Какой именно сервер обработает конкретный запрос, определяет метод балансировки, заданный для группы.
Это руководство описывает балансировку HTTP, которая настраивается в модуле HTTP Upstream. Балансировка TCP- и UDP-сессий устроена так же и настраивается в модуле Stream Upstream; различия отмечены там, где они существенны.
Для группы действует ровно один метод балансировки. Если в блоке задано
несколько методов, применяется последний из них, а в лог записывается
предупреждение Метод определяет принцип, по которому Angie выбирает сервер для запроса, и
каждый метод принимает свой набор параметров директивы server.
Неподдерживаемый параметр не игнорируется: Angie отказывается запускаться и
сообщает Метод Распределяет запросы по Уровень Позиции во взвешенном цикле. Используется по умолчанию, директивы нет. L4, L7 Хэшу произвольного ключа, например URI или заголовка. L4, L7 Хэшу адреса клиента. L7 Наименьшему числу активных соединений на единицу веса. L4, L7 Случайному выбору с учетом веса. L4, L7 Вероятности, обратно пропорциональной среднему времени ответа. L4, L7 feedback (PRO) Вероятности, пропорциональной значению, которое сообщают сами серверы. L4, L7 Все перечисленные методы доступны в Angie, кроме Round-robin — метод по умолчанию: Angie применяет его, если для группы не задан
другой метод, и отдельной директивы для него нет. Серверы группы обходятся по
кругу, и каждому достается доля цикла пропорционально его весу Из каждых семи запросов пять достаются Round-robin служит также запасным вариантом для других методов. Если
hash, ip_hash или random не могут выбрать
работоспособный сервер, выбор передается round-robin. Метод hash направляет все запросы с одинаковым хэшем ключа на один и
тот же сервер. Это удобно, когда серверы группы сами кэшируют ответы, например,
если это кэширующие прокси или узлы memcached. Пока состав группы не меняется,
запросы к одному URI приходят на один и тот же сервер, и ответ кэшируется только
на нем, а не на каждом сервере группы. Ключом может быть любая строка с переменными. Вес
сервера увеличивает долю пространства ключей, которая ему достается. Без параметра Примечание Позиции сервера на кольце вычисляются из имени, записанного в директиве
Без Метод ip_hash использует в качестве ключа адрес клиента: первые три
октета IPv4-адреса или IPv6-адрес целиком. Запросы одного клиента попадают на
один и тот же сервер, пока тот доступен. Режима консистентного хэширования у него нет, поэтому изменение состава группы
может перенаправить многих клиентов на другие серверы. Чтобы вывести сервер из
работы, сохранив остальную часть распределения, пометьте его параметром
Метод least_conn выбирает сервер с наименьшим числом активных
соединений на единицу веса — он минимизирует отношение числа соединений к
весу, а не само число. Поэтому сервер с Учитываются только соединения, по которым сейчас передается запрос. Простаивающие
keepalive-соединения не учитываются. Метод уместен, когда запросы сильно различаются тем, как долго они занимают
сервер: скачивание больших файлов, long polling, WebSocket. Round-robin
отправляет серверам одинаковое с учетом веса число запросов, но оно не отражает
нагрузку, если одни запросы занимают сервер на миллисекунды, а другие на минуты;
Метод random выбирает сервер случайно, с вероятностью, пропорциональной
весу. На большом числе запросов распределение соответствует весам. Параметр Это важно, когда перед одними и теми же серверами работает несколько
балансировщиков, не разделяющих состояние. Если каждый из них выбирает
единственный наименее загруженный сервер, все они нагружают одну и ту же цель;
выбор лучшего из двух случайных кандидатов распределяет нагрузку. Для одного
балансировщика проще использовать least_conn. Примечание Запись Метод least_time отдает предпочтение серверам, которые отвечают
быстрее. Что именно измеряется, задает режим: Группа, где серверы сравниваются по времени получения заголовка ответа: Измерение усредняется по формуле экспоненциально взвешенного скользящего
среднего, поэтому один медленный ответ не смещает оценку сервера далеко.
Директива response_time_factor или параметр Перед выбором этого метода стоит учесть два его свойства. Он не выбирает просто самый быстрый сервер. Обратно пропорциональной
среднему времени ответа является вероятность выбора сервера. Даже стабильно
медленный сервер сохраняет небольшую долю — примерно один процент от того, что
получает средний сервер, то есть около одного запроса из 100 x N для группы из
N серверов. Это сделано намеренно: сервер, не получающий запросов, никогда не
дал бы нового измерения, и его восстановление невозможно было бы обнаружить. Он отвергает параметр В Stream метод least_time принимает другой набор режимов:
Метод feedback (PRO) позволяет самим серверам сообщать, сколько работы они
готовы принять. Angie извлекает значение из каждого ответа — как правило, из
заголовка — и выделяет серверу долю запросов пропорционально этому значению,
усредняя его так же, как least_time усредняет время ответа. Предупреждение Значение трактуется так, как если бы оно означало запас мощности:
чем больше сообщенное значение, тем больше доля запросов. Если ваша
метрика растет по мере роста нагрузки — загрузка процессора, длина очереди —
добавьте параметр Параметр Параметр Метод Что делает round-robin, Задает долю напрямую: она равна весу, деленному на суммарный вес группы. Задает долю пространства ключей. Трафик соответствует весам, только если
сами ключи распределены равномерно; реальные адреса клиентов и URI, как
правило, распределены иначе. Делит сравниваемое число соединений. Сервер с большим весом доводится до
пропорционально большего числа одновременных соединений, а не до
пропорционально большего числа запросов. Ничего — параметр отвергается при запуске. Умножает значение, сообщенное сервером. Вес — лишь один из двух
сомножителей, поэтому долю нельзя предсказать по одному только весу. Как только в игру вступают Angie судит о сервере по результатам отправленных на него запросов. Если
результат попытки допускает повтор и лимит попыток не исчерпан, Angie может
передать запрос другому серверу. Условия повторной попытки задают директива
proxy_next_upstream и ее аналоги, а число и продолжительность попыток
ограничивают proxy_next_upstream_tries и
proxy_next_upstream_timeout. max_fails неудачных попыток в течение
fail_timeout помечают сервер недоступным на тот же
период, после чего он проверяется снова. По умолчанию это одна попытка и десять
секунд. Что считается неудачной попыткой, определяют директива
proxy_next_upstream и ее аналоги. Значение Примечание Отдельные неудачные попытки, не достигающие порога
max_fails, все же стоят серверу части его доли запросов,
которую он возвращает себе не сразу. Без slow_start
у сервера снижается эффективный вес, который учитывают round-robin и
Пассивные проверки узнают о состоянии сервера только из клиентских запросов:
отказ обнаруживается, когда на сервере уже сорвались запросы клиентов, а
восстановление — когда на него снова отправили клиентский запрос. Активные проверки, доступные в Angie PRO, обращаются к серверам по
расписанию, независимо от клиентского трафика, и замечают как отказ, так и
восстановление, не расходуя на это запросы клиентов. Проверку задает директива upstream_probe (PRO) в том же блоке
Каждые пять секунд Angie запрашивает Ответы проверок могут также служить данными для метода feedback через
его параметр Сервер, признанный неработающим, исключается из выбора при любом методе
балансировки. После перезагрузки конфигурации проверки начинаются заново.
Обычно сервер продолжает получать запросы, не дожидаясь первой проверки. Если
проверка задана с параметром Серверы, помеченные параметром Каждый запрос начинает выбор с основных серверов и доходит до резервной группы
только тогда, когда ни один основной сервер не может его принять. Устойчивого
режима отказа, из которого нужно возвращаться, не существует: как только
основной сервер снова проходит проверку, следующий запрос уходит на него. Angie PRO позволяет изменить это поведение директивой
backup_switch (PRO) с параметром Параметр Параметр slow_start возвращает восстановившийся сервер к
его полному весу постепенно, а не сразу: это защищает от полной нагрузки
сервер с холодным кэшем или только что запущенный процесс: Чаще всего параметр срабатывает после того, как сервер был помечен недоступным
и восстановился; кроме того, по той же кривой сервер откатывается назад после
отдельных неудачных попыток (см. Отказы и восстановление). Действует он только с
методами, отмеченными в колонке Чтобы вывести сервер из балансировки намеренно, используйте параметр
Балансировка согласована в пределах экземпляра Angie только тогда, когда
рабочие процессы разделяют общее представление о группе. Его дает директива
zone: Без нее каждый рабочий процесс хранит собственную
копию состояния группы — счетчики отказов, число активных соединений, позицию
в цикле round-robin, средние времена ответа — и балансирует независимо от
остальных. При N рабочих процессах вы фактически получаете N
балансировщиков над одними и теми же серверами: один процесс может считать
сервер недоступным, пока остальные продолжают слать на него запросы, а
ограничение Зона также делает группу видимой для
метрик upstream-групп и необходима для
параметров Примечание Перезагрузка конфигурации создает зону заново независимо от того,
изменилось ли значение Балансировка определяет, куда уйдет запрос. Две директивы ограничивают это
решение: Привязывает клиентскую сессию к серверу, который обслужил ее первым;
сессия опознается по cookie, по значению маршрута или — в режиме
Ненадолго удерживает запрос, если ни один сервер не может его принять,
вместо того чтобы сразу вернуть ошибку. Полезно, когда при коротких
всплесках нагрузки достигается предел Директива keepalive на выбор сервера не влияет: она держит открытыми
неактивные соединения с серверами, чтобы запрос к уже выбранному серверу
использовал одно из них, а не открывал новое. Число таких соединений
ограничивается в пределах рабочего процесса, а не суммарно. Предупреждение Директивы load balancing method redefined; если не задано ни
одного, используется Взвешенный round-robin.Выбор метода#
balancing method does not support parameter. Сверьтесь с
таблицей, прежде чем сочетать метод с параметрами weight,
slow_start или backup.weightslow_startbackupfeedback, для
которого нужен Angie PRO. У ip_hash нет аналога в Stream;
используйте вместо него hash с переменной $remote_addr.Методы балансировки#
Взвешенный round-robin#
weight:upstream backend {
zone backend 1m;
server backend1.example.com weight=5;
server backend2.example.com;
server backend3.example.com;
}
backend1.example.com и по одному
двум другим серверам. Распределение при этом равномерное: запросы к серверу
с большим весом распределяются по всему циклу, а не отправляются подряд одной
группой, поэтому группа не получает пять запросов подряд на один сервер, а
затем два на остальные.hash#
upstream backend {
zone backend 1m;
hash $request_uri consistent;
server backend1.example.com;
server backend2.example.com;
}
consistent Angie сопоставляет хэш ключа с суммарным весом
группы: каждому серверу отведен отрезок, равный его весу. Поэтому изменение
состава группы меняет суммарный вес и переназначает много ключей помимо тех,
что приходились на добавленный или удаленный сервер: закэшированные ответы
для этих ключей остаются на серверах, куда запросы с ними больше не приходят.
С параметром consistent Angie размещает серверы на кольце
ketama,
и при удалении сервера переназначаются только те ключи, которые обслуживал он.server, а не из адресов, в которые это имя разрешается. Все адреса
одного имени делят эти позиции, поэтому такое имя занимает на кольце столько
же места, сколько один сервер того же веса. Когда ключ попадает на позицию
имени, Angie выбирает один из его адресов по принципу round-robin.consistent каждый адрес считается отдельным сервером со своим
весом, и хэш сопоставляется с суммарным весом всех адресов. Поэтому имени,
которое разрешается в несколько адресов, достается доля, пропорциональная
числу этих адресов.ip_hash#
down, а не удаляйте его строку:upstream backend {
zone backend 1m;
ip_hash;
server backend1.example.com;
server backend2.example.com down;
server backend3.example.com;
}
least_conn#
weight=2 и 15 соединениями
предпочтительнее сервера с weight=1 и 10 соединениями. Если несколько
серверов равны по этому показателю, они перебираются взвешенным round-robin.least_conn учитывает запросы, которые сервер обрабатывает в данный
момент. Если же серверы различаются скоростью, подойдет least_time.random#
two выбирает два случайных сервера, а затем из них — тот, у
которого меньше активных соединений на единицу веса:upstream backend {
zone backend 1m;
random two;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
random two least_conn принимается для совместимости и
работает точно так же, как random two: сравнение активных соединений
— единственный режим параметра two.least_time#
header — время до
получения заголовка ответа, last_byte — время до получения ответа
целиком.upstream backend {
zone backend 1m;
least_time header;
server backend1.example.com;
server backend2.example.com;
}
factor задают, какой
вклад в новое значение дает накопленная история по сравнению с очередным
измерением: высокий коэффициент означает медленную реакцию, низкий — быстрое
забывание истории.weight. Группа, в которой least_time
сочетается с weight= хотя бы у одного сервера, не запустится. Время
ответа уже отражает то, сколько нагрузки принимает сервер, так что весу нечего
добавить.connect (время установки соединения с сервером), first_byte
(время до получения первого байта данных от сервера) и last_byte (время
до завершения сессии); режима header там нет.feedback#
upstream backend {
zone backend 1m;
feedback $upstream_http_x_capacity;
server backend1.example.com;
server backend2.example.com;
}
inverse, иначе больше всего трафика получит самый
загруженный сервер.account задает, какие ответы участвуют в расчете среднего; это
позволяет строить балансировку на ответах upstream_probe (PRO), а не на
клиентском трафике.Веса серверов и доли трафика#
weight означает разное для разных методов, и лишь у части из
них доля трафика сервера равна его весу, деленному на сумму весов:weightrandomhash, ip_hashleast_connleast_timefeedbackmax_conns, slow_start,
max_fails, down или резервные серверы, ни один метод не
распределяет трафик строго по весам.Отказы и восстановление#
Пассивные проверки#
max_fails=0 отключает проверку для этого сервера: он никогда
не будет помечен недоступным.least_conn; сервер отыгрывает его обратно на последующих запросах.
Со slow_start каждая такая неудача отбрасывает сервер назад по
кривой разгона, которую учитывают все методы, принимающие этот параметр;
здесь возврат к полному весу идет по времени, а не по числу запросов.
В обоих случаях нужно, чтобы
max_fails был больше единицы: при значении по умолчанию, равном
единице, первая же неудачная попытка сразу помечает сервер недоступным, и
промежуточного состояния не возникает.Активные проверки#
location, где запросы передаются в группу; самой группе нужна зона
разделяемой памяти:upstream backend {
zone backend 1m;
server backend1.example.com;
server backend2.example.com;
}
map $upstream_status $good {
200 "1";
}
server {
listen 80;
location / {
proxy_pass http://backend;
upstream_probe backend_probe uri=/health interval=5s
test=$good fails=3 passes=2;
}
}
/health у каждого сервера группы.
Три неудачные проверки подряд помечают сервер неработающим, две успешные подряд
возвращают его в работу. Без параметра test проверка считается
успешной по тем же правилам, что и клиентский запрос в этом location:
по умолчанию proxy_next_upstream считает неудачей только ошибку и
таймаут, поэтому ответ 500 или 503 проверку не проваливает.
Здесь test=$good засчитывает проверку, только если сервер ответил
кодом 200: для любого другого кода map оставляет переменную
пустой.account.essential, сервер не получает запросов,
пока проверка впервые не признает его работоспособным (в этом примере — после
двух успешных проверок подряд); параметр persistent, который действует
только вместе с essential, снимает такое ожидание для серверов, которые
до перезагрузки считались работающими: признак работоспособности сохраняется в
зоне (см. Общее состояние рабочих процессов).Резервные серверы#
backup, находятся в резерве:upstream backend {
zone backend 1m;
server backend1.example.com;
server backend2.example.com;
server backup1.example.com backup;
}
permanent, которая продолжает
направлять запросы в группу, обслужившую их последней. Без указания времени
переключение не отменяется само; с параметром permanent=время
Angie по истечении этого интервала отправляет один запрос в основную группу,
чтобы проверить, восстановилась ли она.backup отвергается методами hash, ip_hash
и random.Возврат сервера в работу#
server backend1.example.com slow_start=30s;
slow_start в разделе
Выбор метода. В отличие от некоторых других реализаций, зона разделяемой
памяти (zone) для него не требуется.down; чтобы прекратить направлять на него новый трафик, дав завершиться
уже привязанным сессиям, — параметр drain.Общее состояние рабочих процессов#
upstream backend {
zone backend 1m;
server backend1.example.com;
server backend2.example.com;
}
max_conns действует в пределах процесса, допуская в N раз
больше соединений, чем задано.resolve и service директивы server.size: счетчики, состояние пассивных проверок
и накопленная история балансировки начинаются с нуля. Переносятся адреса,
в которые разрешились серверы с параметром resolve, а также признак
работоспособности, на который опираются активные проверки с параметром
persistent (см. Активные проверки).Привязка сессий и смежные механизмы#
learn — по значению, которое Angie видит в трафике. Пока сессия
жива, привязка имеет приоритет над методом балансировки.max_conns.sticky, keepalive и queue должны следовать
после директивы, задающей метод балансировки, иначе они не работают.