Модуль http_upstream#

Предоставляет контекст для описания группы серверов, которые могут использоваться в директивах proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass, memcached_pass и grpc_pass.

Пример конфигурации#

upstream backend {
    zone backend 1m;
    server backend1.example.com       weight=5;
    server backend2.example.com:8080;
    server backend3.example.com       service=_example._tcp resolve;
    server unix:/tmp/backend3;

    server backup1.example.com:8080   backup;
    server backup2.example.com:8080   backup;
}

resolver 127.0.0.53 status_zone=resolver;

server {
    location / {
        proxy_pass http://backend;
    }
}

Директивы#

upstream#

Синтаксис:

upstream имя { … }

Умолчание:

Контекст:

http

Описывает группу серверов. Серверы могут слушать на разных портах. Кроме того, можно одновременно использовать серверы, слушающие на TCP- и UNIX-сокетах.

Пример:

upstream backend {
    server backend1.example.com weight=5;
    server 127.0.0.1:8080       max_fails=3 fail_timeout=30s;
    server unix:/tmp/backend3;

    server backup1.example.com  backup;
}

По умолчанию запросы распределяются по серверам циклически (в режиме round-robin) с учётом весов серверов. В вышеприведённом примере каждые 7 запросов будут распределены так: 5 запросов на backend1.example.com и по одному запросу на второй и третий серверы.

Если при попытке работы с сервером происходит ошибка, то запрос передаётся следующему серверу, и так далее до тех пор, пока не будут опробованы все работающие серверы. Если не удастся получить успешный ответ ни от одного из серверов, то клиенту будет возвращён результат работы с последним сервером.

upstream_probe#

Важно

Директива доступна только в версии PRO.

Синтаксис:

upstream_probe имя [uri=адрес] [port=число] [interval=время] [test=условие] [essential] [fails=число] [passes=число] [max_body=размер] [mode=always|idle|onfail];

Умолчание:

Контекст:

location

Задаёт активную проверку работоспособности серверов тех upstream, которые указаны в директивах proxy_pass, uwsgi_pass и т. д. в том же контексте location, где находится директива upstream_probe. При этом Angie регулярно выполняет запросы согласно указанным параметрам к каждому серверу в составе апстрима.

Сервер проходит проверку, если запрос к нему успешно выполняется с учётом всех параметров самой директивы upstream_probe и всех параметров, влияющих на использование апстримов тем контекстом location, где она задана. Это касается в том числе директив proxy_next_upstream, uwsgi_next_upstream и пр., а также proxy_set_header и т. д.

Чтобы использовать проверки, в апстриме необходима зона разделяемой памяти (zone). Для одного апстрима можно определить несколько проверок.

Могут быть заданы следующие параметры:

имя

Обязательное имя проверки.

uri

URI запроса, который добавляется к аргументу proxy_pass, uwsgi_pass и т. д.
По умолчанию — /.

port

Альтернативный порт для запроса.

interval

Интервал между проверками.
По умолчанию — 5s.

method

HTTP-метод запроса проверки.
По умолчанию — GET.

test

Проверяемое при запросе условие; задаётся строкой из переменных. Если результат подстановки всех переменных даёт "" или "0", проверка не пройдена.

essential

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

fails

Число последовательных неуспешных запросов, при котором проверка считает сервер неработающим.
По умолчанию — 1.

passes

Число последовательных успешных запросов, при котором проверка считает сервер работающим.
По умолчанию — 1.

max_body

Максимальный объём памяти для тела ответа.
По умолчанию — 256k.

mode

Режим проверки в зависимости от работоспособности серверов:

  • always — серверы проверяются независимо от состояния;

  • idle — проверяются неработающие серверы, а также серверы, где с последнего клиентского запроса прошло время interval.

  • onfail — проверяются серверы только в неработающем состоянии.

По умолчанию — always.

Пример:

upstream backend {
    zone backend 1m;

    server backend1.example.com;
    server backend2.example.com;
}

map $upstream_status $good {
    200     "1";
}

server {
    listen ...;

    location @probes {
        ...
        proxy_pass http://backend;

        upstream_probe backend_probe
            uri=/probe
            port=10004
            interval=5s
            test=$good
            essential
            fails=3
            passes=3
            max_body=10m
            mode=idle;
    }
}

Детали работы:

  • Изначально сервер не получает клиентские запросы, пока не пройдёт все заданные для него проверки с параметром essential. Если таких проверок нет, сервер считается работающим.

  • Сервер считается неработающим и не получает клиентские запросы, если какая-либо заданная для него проверка достигает своего порога fails или сам сервер достигает порога max_fails.

  • Чтобы неработавший сервер снова считался работающим, все заданные для него проверки должны достичь своего порога passes.

server#

Синтаксис:

server адрес [параметры];

Умолчание:

Контекст:

upstream

Задаёт адрес и другие параметры сервера. Адрес может быть указан в виде доменного имени или IP-адреса, и необязательного порта, или в виде пути UNIX-сокета, который указывается после префикса «unix:». Если порт не указан, используется порт 80. Доменное имя, которому соответствует несколько IP-адресов, задаёт сразу несколько серверов.

Могут быть заданы следующие параметры:

weight=число

задаёт вес сервера
по умолчанию 1.

max_conns=число

ограничивает максимальное число одновременных активных соединений к проксируемому серверу.
Значение по умолчанию равно 0 и означает, что ограничения нет. Если группа не находится в зоне разделяемой памяти, то ограничение работает отдельно для каждого рабочего процесса.

Примечание

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

max_fails=число — задаёт число неудачных попыток работы с сервером, которые должны произойти в течение времени, заданного параметром fail_timeout, чтобы сервер считался недоступным на период времени, также заданный параметром fail_timeout.
Что считается неудачной попыткой, определяется директивами proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream, memcached_next_upstream и grpc_next_upstream.

При превышении max_fails сервер также признаётся неработающим с точки зрения upstream_probe; клиентские запросы не будут направляться к нему, пока проверки не признают его работающим.

max_fails=1

число попыток по умолчанию

max_fails=0

отключает учёт попыток

fail_timeout=время — задаёт:

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

  • и время, в течение которого сервер будет считаться недоступным.
    По умолчанию параметр равен 10 секундам.

backup

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

down

помечает сервер как постоянно недоступный.

Осторожно

Параметр backup нельзя использовать совместно с методами балансировки нагрузки hash, ip_hash и random.

Добавлено в версии 1.1.0.

resolve

позволяет отслеживать изменения списка IP-адресов, соответствующего доменному имени, и обновлять его без перезагрузки конфигурации. Для работы параметра директивы resolver и resolver_timeout должны быть заданы в блоке upstream или унаследованы из блока http.

service=имя

включает преобразование SRV-записей DNS и задаёт имя сервиса. Для работы параметра необходимо задать параметр resolve у сервера, не указывая порт сервера при имени хоста.

Добавлено в версии 1.2.0.

sid=id

задаёт ID сервера в группе.
Если параметр не задан, то ID задаётся как шестнадцатеричный MD5-хэш IP-адреса и порта или пути UNIX-сокета.

zone#

Синтаксис:

zone имя [размер];

Умолчание:

Контекст:

upstream

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

hash#

Синтаксис:

hash ключ [consistent];

Умолчание:

Контекст:

upstream

Задаёт метод балансировки нагрузки для группы, при котором соответствие клиента серверу определяется при помощи хэшированного значения ключа. В качестве ключа может использоваться текст, переменные и их комбинации. Следует отметить, что любое добавление или удаление серверов в группе может привести к перераспределению большинства ключей на другие серверы. Метод совместим с библиотекой Perl Cache::Memcached.

Если задан параметр consistent, то вместо вышеописанного метода будет использоваться метод консистентного хэширования ketama. Метод гарантирует, что при добавлении сервера в группу или его удалении на другие серверы будет перераспределено минимальное число ключей. Применение метода для кэширующих серверов обеспечивает больший процент попаданий в кэш. Метод совместим с библиотекой Perl Cache::Memcached::Fast при значении параметра ketama_points равным 160.

ip_hash#

Синтаксис:

ip_hash;

Умолчание:

Контекст:

upstream

Задаёт для группы метод балансировки нагрузки, при котором запросы распределяются по серверам на основе IP-адресов клиентов. В качестве ключа для хэширования используются первые три октета IPv4-адреса клиента или IPv6-адрес клиента целиком. Метод гарантирует, что запросы одного и того же клиента будут всегда передаваться на один и тот же сервер. Если же этот сервер будет считаться недоступным, то запросы этого клиента будут передаваться на другой сервер. С большой долей вероятности это также будет один и тот же сервер.

Если один из серверов нужно убрать на некоторое время, то для сохранения текущего хэширования IP-адресов клиентов этот сервер нужно пометить параметром down:

upstream backend {
    ip_hash;

    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com down;
    server backend4.example.com;
}

keepalive#

Синтаксис:

keepalive соединения;

Умолчание:

Контекст:

upstream

Задействует кэш соединений для группы серверов.

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

Примечание

Следует особо отметить, что директива keepalive не ограничивает общее число соединений с серверами группы, которые рабочие процессы Angie могут открыть. Параметр соединения следует устанавливать достаточно консервативно, чтобы серверы группы по-прежнему могли обрабатывать новые входящие соединения.

Внимание

Директива keepalive должна использоваться после всех директив, задающих тот или иной метод балансировки нагрузки, иначе она не будет работать.

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

upstream memcached_backend {
    server 127.0.0.1:11211;
    server 10.0.0.2:11211;

    keepalive 32;
}

server {
    #...

    location /memcached/ {
        set $memcached_key $uri;
        memcached_pass memcached_backend;
    }

}

Для HTTP директиву proxy_http_version следует установить в «1.1», а поле заголовка «Connection» — очистить:

upstream http_backend {
    server 127.0.0.1:8080;

    keepalive 16;
}

server {
    #...

    location /http/ {
        proxy_pass http://http_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    #    ...
    }
}

Примечание

Хоть это и не рекомендуется, но также возможно использование постоянных соединений с HTTP/1.0, путём передачи поля заголовка «Connection: Keep-Alive» серверу группы.

Для работы постоянных соединений с FastCGI-серверами потребуется включить директиву fastcgi_keep_conn:

upstream fastcgi_backend {
    server 127.0.0.1:9000;

    keepalive 8;
}

server {
    #...

    location /fastcgi/ {
        fastcgi_pass fastcgi_backend;
        fastcgi_keep_conn on;
    #    ...
    }
}

Примечание

Протоколы SCGI и uwsgi не определяют семантику постоянных соединений.

keepalive_requests#

Синтаксис:

keepalive_requests число;

Умолчание:

keepalive_requests 1000;

Контекст:

upstream

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

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

keepalive_time#

Синтаксис:

keepalive_time время;

Умолчание:

keepalive_time 1h;

Контекст:

upstream

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

keepalive_timeout#

Синтаксис:

keepalive_timeout время;

Умолчание:

keepalive_timeout 60s;

Контекст:

upstream

Задаёт таймаут, в течение которого неактивное постоянное соединение с сервером группы не будет закрыто.

bind_conn#

Важно

Директива доступна только в версии PRO.

Синтаксис:

bind_conn значение;

Умолчание:

Контекст:

upstream

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

Внимание

Директива bind_conn должна использоваться после всех директив, задающих тот или иной метод балансировки нагрузки, иначе она не будет работать.

Внимание

При использовании директивы настройки модуля http_proxy должны допускать использование постоянных соединений, например:

proxy_http_version 1.1;
proxy_set_header Connection "";

Типичный пример использования директивы — проксирование соединений с NTLM-аутентификацией, где требуется обеспечить привязку клиента к серверу в начале согласования:

map $http_authorization   $ntlm {
    ~*^N(?:TLM|egotiate)  1;
}

upstream ntlm_backend {
    server 127.0.0.1:8080;
    bind_conn $ntlm;
}

server {
    # ...
    location / {
        proxy_pass http://ntlm_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        # ...
    }
}

least_conn#

Синтаксис:

least_conn;

Умолчание:

Контекст:

upstream

Задаёт для группы метод балансировки нагрузки, при котором запрос передаётся серверу с наименьшим числом активных соединений, с учётом весов серверов. Если подходит сразу несколько серверов, они выбираются циклически (в режиме round-robin) с учётом их весов.

least_time#

Важно

Директива доступна только в версии PRO.

Синтаксис:

least_time header | last_byte;

Умолчание:

Контекст:

upstream

Задаёт для группы метод балансировки нагрузки, при котором вероятность передачи запроса активному серверу обратно пропорциональна среднему времени его ответа; чем оно меньше, тем больше запросов будет получать сервер.

В режиме header учитывается среднее время получения заголовков ответа; в режиме last_byte — среднее время получения полного ответа.

Подсчёт средних значений управляется директивой response_time_factor. Текущие значения представлены как header_time (только заголовки) и response_time (ответы целиком) в объекте health сервера среди метрик апстрима в API.

random#

Синтаксис:

random [two];

Умолчание:

Контекст:

upstream

Задаёт для группы метод балансировки нагрузки, при котором запрос передаётся случайно выбранному серверу, с учётом весов серверов.

Если указан необязательный параметр two, Angie случайным образом выбирает два сервера, из которых выбирает сервер, используя метод least_conn, при котором запрос передаётся на сервер с наименьшим количеством активных соединений.

response_time_factor#

Важно

Директива доступна только в версии PRO.

Синтаксис:

response_time_factor число;

Умолчание:

response_time_factor 90;

Контекст:

upstream

Задаёт для метода балансировки нагрузки least_time коэффициент сглаживания предыдущего значения при вычислении среднего времени ответа по формуле экспоненциально взвешенного скользящего среднего.

Чем больше указанное число, тем меньше новые значения влияют на среднее; если указать 90, то будет взято 90 % от предыдущего значения и лишь 10 % от нового. Допустимые значения — от 0 до 99 включительно.

Текущие результаты вычислений представлены как header_time (только заголовки) и response_time (ответы целиком) в объекте health сервера среди метрик апстрима в API.

Примечание

При подсчёте учитываются только успешные ответы; что считать неуспешным ответом, определяют директивы proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream, memcached_next_upstream и grpc_next_upstream. Кроме того, значение header_time пересчитывается, только если получены и обработаны все заголовки, а response_time — только если получен весь ответ.

sticky#

Добавлено в версии 1.2.0.

Синтаксис:

sticky cookie name [attr1=value] [attr2=value] [attr3] …;
sticky route $variable [$variable2] [$variable3] …;

Умолчание:

Контекст:

upstream

Сконфигурировать привязку клиентских сессий можно одним из режимов: cookie или route указанием первого параметра.

cookie: данные о назначенном сервере передаются в HTTP куке, сгенерированной Angie.

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

Внимание

Директива sticky должна использоваться после всех директив, задающих тот или иной метод балансировки нагрузки, иначе она не будет работать.

Атрибуты куки можно назначать, единственный атрибут, устанавливаемый по умолчанию, — path=/. Для назначения атрибутов куки можно использовать строки, переменные и их комбинации. Чтобы снять атрибут, достаточно сконфигурировать его с пустым значением: attr=. К примеру, со sticky cookie path= Angie установит куку без атрибута path.

upstream backend {
    server backend1.example.com:8080;
    server backend2.example.com:8080;

    sticky cookie example domain=$my_domain max-age=3600;
}

Значение куки берется из параметра sid; если задана директива sticky_secret, оно дополнительно хэшируется.

route: проксируемый сервер назначает клиенту route в начале сессии.

При использовании метода route проксируемый сервер назначает клиенту маршрут по получении первого запроса. Все последующие запросы от этого клиента будут содержать информацию о маршруте в куке или URI. Эта информация сравнивается с параметром sid директивы server для идентификации сервера, на который следует проксировать запрос. Если назначенный сервер не может обработать запрос, выбирается новый сервер согласно настроенному методу балансировки как если бы в запросе не было информации о маршруте.

upstream backend {
    server backend1.example.com:8080 sid="server1";
    server backend2.example.com:8080 sid="server2";

    sticky route $cookie_route $arg_route;
}

При такой конфигурации Angie будет искать sid сначала в куке 'route', затем в аргументе запроса (в URI) 'route'.

sticky_strict#

Добавлено в версии 1.2.0.

Синтаксис:

sticky_strict on | off;

Умолчание:

sticky_strict off;

Контекст:

upstream

Позволяет возвращать ошибку 502 в случаях, когда назначенный клиенту сервер в апстриме недоступен.
По умолчанию из группы серверов выбирается другой доступный сервер.

sticky_secret#

Добавлено в версии 1.2.0.

Синтаксис:

sticky_secret $complex_value;

Умолчание:

Контекст:

upstream

Добавляет соль в функцию хэширования при генерации значения куки. Параметр может быть задан с использованием переменных, например, $remote_addr:

upstream backend {
    server backend1.example.com:8080;
    server backend2.example.com:8080;

    sticky cookie cookie_name;
    sticky_secret my_secret.$remote_addr;
}

resolver#

Добавлено в версии 1.1.0.

Синтаксис:

resolver адрес … [valid=время] [ipv4=on|off] [ipv6=on|off] [status_zone=зона];

Умолчание:

Контекст:

upstream

Задаёт серверы DNS, используемые для преобразования имён вышестоящих серверов в адреса, например:

resolver 127.0.0.53 [::1]:5353;

Адрес может быть указан в виде доменного имени или IP-адреса, и необязательного порта. Если порт не указан, используется порт 53. Серверы DNS опрашиваются циклически.

По умолчанию Angie кэширует ответы, используя значение TTL из ответа.

valid

необязательный параметр, позволяет переопределить срок кэширования ответа

resolver 127.0.0.53 [::1]:5353 valid=30s;

По умолчанию Angie будет искать как IPv4-, так и IPv6-адреса при преобразовании имён в адреса.

ipv4=off

запрещает поиск IPv4-адресов

ipv6=off

запрещает поиск IPv6-адресов

status_zone

необязательный параметр, включает сбор информации о запросах и ответах сервера DNS в указанной зоне

Совет

Для предотвращения DNS-спуфинга рекомендуется использовать DNS-серверы в защищённой доверенной локальной сети.

resolver_timeout#

Добавлено в версии 1.1.0.

Синтаксис:

resolver_timeout время;

Умолчание:

resolver_timeout 30s;

Контекст:

upstream

Задаёт таймаут для преобразования имени в адрес, например:

resolver_timeout 5s;

Встроенные переменные#

Модуль http_upstream поддерживает следующие встроенные переменные:

$upstream_addr#

хранит IP-адрес и порт или путь к UNIX-сокету сервера группы. Если при обработке запроса были сделаны обращения к нескольким серверам, то их адреса разделяются запятой, например:

192.168.1.1:80, 192.168.1.2:80, unix:/tmp/sock

Если произошло внутреннее перенаправление от одной группы серверов на другую с помощью «X-Accel-Redirect» или error_page, то адреса, соответствующие разным группам серверов, разделяются двоеточием, например:

192.168.1.1:80, 192.168.1.2:80, unix:/tmp/sock : 192.168.10.1:80, 192.168.10.2:80

Если сервер не может быть выбран, то переменная хранит имя группы серверов.

$upstream_bytes_received#

число байт, полученных от сервера группы. Значения нескольких соединений разделяются запятыми и двоеточиями подобно адресам в переменной $upstream_addr.

$upstream_bytes_sent#

число байт, переданных на сервер группы. Значения нескольких соединений разделяются запятыми и двоеточиями подобно адресам в переменной $upstream_addr.

$upstream_cache_status#

хранит статус доступа к кэшу ответов. Статус может быть одним из «MISS», «BYPASS», «EXPIRED», «STALE», «UPDATING», «REVALIDATED» или «HIT».

$upstream_connect_time#

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

$upstream_header_time#

хранит время, затраченное на получение заголовка ответа от сервера группы; время хранится в секундах с точностью до миллисекунд. Времена нескольких ответов разделяются запятыми и двоеточиями подобно адресам в переменной $upstream_addr.

$upstream_http_ имя#

хранят поля заголовка ответа сервера. Например, поле заголовка ответа «Server» доступно в переменной $upstream_http_server. Правила преобразования имён полей заголовка ответа в имена переменных такие же, как для переменных с префиксом «$http_». Необходимо иметь в виду, что поля заголовка запоминаются только из ответа последнего сервера.

$upstream_probe_body#

Тело ответа от сервера, полученного при проверке upstream_probe. Его размер ограничен параметром max_body.

$upstream_response_length#

хранит длину ответа, полученного от сервера группы; длина хранится в байтах. Длины нескольких ответов разделяются запятыми и двоеточиями подобно адресам в переменной $upstream_addr.

$upstream_response_time#

хранит время, затраченное на получение ответа от сервера группы; время хранится в секундах с точностью до миллисекунд. Времена нескольких ответов разделяются запятыми и двоеточиями подобно адресам в переменной $upstream_addr.

$upstream_status#

хранит статус ответа, полученного от сервера группы. Статусы нескольких ответов разделяются запятыми и двоеточиями подобно адресам в переменной $upstream_addr. Если сервер не может быть выбран, то переменная хранит статус 502 (Bad Gateway).

$upstream_sticky_status#

Статус привязанного запроса.

''

запрос к upstream не обрабатывался модулем http_upstream_sticky

NEW

запрос не содержит информации о привязке к серверу

HIT

запрос с привязкой отправлен на соответствующий сервер

MISS

запрос с привязкой отправлен на сервер, выбранный по алгоритму балансировки

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

$upstream_trailer_ имя#

хранит поля из конца ответа, полученного от сервера группы.