<!-- review: finished -->

<a id="stream-upstream"></a>

# Upstream

Предоставляет контекст для описания группы серверов, которые могут использоваться в директиве [proxy_pass](https://angie.software//angie/docs/configuration/modules/stream/stream_proxy.md#s-proxy-pass).

<a id="configuration-example-73"></a>

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

```nginx
upstream backend {
    hash $remote_addr consistent;
    zone backend 1m;

    server backend1.example.com:1935  weight=5;
    server unix:/tmp/backend3;
    server backend3.example.com       service=_example._tcp resolve;

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

resolver 127.0.0.53 status_zone=resolver;

server {
    listen 1936;
    proxy_pass backend;
}
```

<a id="directives-82"></a>

## Директивы

<a id="index-0"></a>

<a id="s-u-upstream"></a>

### upstream

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `upstream` имя { ... }   |
|------------------------------------------------------------------------------------------|--------------------------|
| По умолчанию                                                                             | —                        |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | stream                   |

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

Пример:

```nginx
upstream backend {
    server backend1.example.com:1935 weight=5;
    server 127.0.0.1:1935            max_fails=3 fail_timeout=30s;
    server unix:/tmp/backend2;
    server backend3.example.com:1935 resolve;

    server backup1.example.com:1935  backup;
}
```

<a id="s-round-robin"></a>

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

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

<a id="index-1"></a>

<a id="s-u-server"></a>

### server

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `server` адрес [параметры];   |
|------------------------------------------------------------------------------------------|-------------------------------|
| По умолчанию                                                                             | —                             |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | upstream                      |

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

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

| `weight=`число    | Задает вес сервера. По умолчанию — 1.                                                                                                                                                                                                                                                        |
|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `max_conns=`число | Ограничивает максимальное число одновременных активных соединений к проксируемому серверу. Значение по умолчанию равно `0` и означает, что ограничения нет. Если группа не находится в [зоне](#s-u-zone) разделяемой памяти, то ограничение работает отдельно для каждого рабочего процесса. |

<a id="s-max-fails"></a>

`max_fails=`число — задает число неудачных попыток связи с сервером,
которые должны произойти в течение заданного [fail_timeout](#s-fail-timeout) времени для того, чтобы сервер считался недоступным; после
этого он будет повторно проверен через то же самое время.

В данном случае неудачной попыткой считается ошибка или таймаут при установке
соединения с сервером.

#### NOTE
Если директива `server` в группе разрешается в несколько серверов,
ее настройка `max_fails` применяется к каждому серверу отдельно.

Если после разрешения всех директив `server`
в апстриме остается только один сервер,
настройка `max_fails` не действует и будет проигнорирована.

| `max_fails=1`   | Число попыток по умолчанию.   |
|-----------------|-------------------------------|
| `max_fails=0`   | Отключает учет попыток.       |

<a id="s-fail-timeout"></a>

`fail_timeout=`время — задает период времени, в течение которого
должно произойти определенное число неудачных попыток связи с сервером
([max_fails](#s-max-fails)), чтобы сервер считался недоступным.
Затем сервер остается недоступным в течение того же самого времени,
прежде чем будет проверен повторно.

Значение по умолчанию — 10 секунд.

#### NOTE
Если директива `server` в группе разрешается в несколько серверов,
ее настройка `fail_timeout` применяется к каждому серверу отдельно.

Если после разрешения всех директив `server`
в апстриме остается только один сервер,
настройка `fail_timeout` не действует и будет проигнорирована.

| `backup`      | Помечает сервер как запасной. На него будут передаваться запросы в случае, если не работают основные серверы.                                                                                                   |
|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `down`        | Помечает сервер как постоянно недоступный.                                                                                                                                                                      |
| `drain` (PRO) | Помечает сервер как разгружаемый (draining); это значит,<br/>что он получает только запросы сессий,<br/>привязанных ранее через [sticky](#s-u-sticky).<br/>В остальном поведение такое же, как в режиме `down`. |

#### WARNING
Параметр `backup` нельзя использовать совместно с методами
балансировки нагрузки [hash](#s-u-hash) и [random](#s-u-random).

Параметры `down` и `drain` взаимно исключающие.

<a id="s-reresolve"></a>

| `resolve`     | Позволяет отслеживать изменения списка IP-адресов, соответствующего<br/>доменному имени, и обновлять его без перезагрузки конфигурации.<br/>При этом группа должна находиться в<br/>[зоне разделяемой памяти](#s-u-zone);<br/>также должен быть определен<br/>[преобразователь имен в адреса](https://angie.software//angie/docs/configuration/modules/stream/index.md#s-resolver).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `service=`имя | Включает преобразование SRV-записей DNS и задает имя сервиса. При<br/>указании этого параметра необходимо также задать параметр resolve,<br/>не указывая порт сервера при имени хоста.<br/><br/>Если в имени службы нет точек, формируется имя по стандарту RFC:<br/>к имени службы добавляется префикс `_`,<br/>затем через точку добавляется `_tcp`.<br/>Так, имя службы `http` даст в результате `_http._tcp`.<br/><br/>Angie разрешает SRV-записи,<br/>объединяя нормализованное имя службы и имя хоста<br/>и получая список серверов для полученной комбинации через DNS,<br/>вместе с их приоритетами и весами.<br/><br/>- SRV-записи с наивысшим приоритетом<br/>  (те, которые имеют минимальное значение приоритета)<br/>  разрешаются как основные серверы,<br/>  а прочие записи становятся запасными серверами.<br/>  Если `backup` установлено с `server`,<br/>  SRV-записи с наивысшим приоритетом разрешаются как запасные серверы,<br/>  а прочие записи игнорируются.<br/>- Вес аналогичен параметру `weight` директивы `server`.<br/>  Если вес задан как в самой директиве, так и в SRV-записи,<br/>  используется вес, установленный в директиве. |

В этом примере выполняется поиск записи `_http._tcp.backend.example.com`:

```nginx
server backend.example.com service=http resolve;
```

| `sid=`id   | Задает ID сервера в группе. Если параметр не задан,<br/>то ID задается как шестнадцатеричный MD5-хэш<br/>IP-адреса и порта или пути UNIX-сокета.   |
|------------|----------------------------------------------------------------------------------------------------------------------------------------------------|

<a id="s-slow-start"></a>

| `slow_start=`время   | Задает [время](https://angie.software//angie/docs/configuration/configfile.md#syntax) восстановления веса сервера,<br/>возвращающегося к работе<br/>при балансировке нагрузки методом<br/>[round-robin](https://angie.software//angie/docs/configuration/modules/http/http_upstream.md#round-robin) или [least_conn](#s-u-least-conn).<br/><br/>Если параметр задан<br/>и сервер после сбоя снова считается работающим<br/>с точки зрения [max_fails](#s-max-fails) и [upstream_probe (PRO)](https://angie.software//angie/docs/configuration/modules/stream/stream_upstream_probe.md#s-u-upstream-probe),<br/>то такой сервер равномерно набирает указанный для него вес<br/>в течение заданного времени.<br/><br/>Если параметр не задан,<br/>то в аналогичной ситуации<br/>сервер сразу начинает работу с указанным для него весом.   |
|----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

#### NOTE
Если в апстриме задан только один `server`,
`slow_start` не работает и будет игнорироваться.

<a id="index-2"></a>

<a id="s-u-state"></a>

### state (PRO)

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `state` файл;   |
|------------------------------------------------------------------------------------------|-----------------|
| По умолчанию                                                                             | —               |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | upstream        |

Указывает файл, где постоянно хранится список серверов апстрима.
При установке из
[наших пакетов](https://angie.software//angie/docs/installation/index.md#install-packages)
для хранения таких файлов специально создается каталог
`/var/lib/angie/state/` (`/var/db/angie/state/` во FreeBSD)
с соответствующими правами доступа,
и в конфигурации остается добавить лишь имя файла:

```nginx
upstream backend {

    zone backend 1m;
    state /var/lib/angie/state/<ИМЯ ФАЙЛА>;
}
```

Список серверов здесь имеет формат, аналогичный `s_server`.
Содержимое файла изменяется при любом изменении серверов в разделе
[/config/stream/upstreams/](https://angie.software//angie/docs/configuration/modules/http/http_api.md#api-config-stream-upstreams-servers)
через API конфигурации.
Файл считывается при запуске Angie или перезагрузке конфигурации.

#### WARNING
Чтобы использовать директиву `state` в блоке `upstream`,
в нем не должно быть директив `server`,
но нужна зона разделяемой памяти ([zone](#s-u-zone)).

<a id="index-3"></a>

<a id="s-u-zone"></a>

### zone

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `zone` имя [размер];   |
|------------------------------------------------------------------------------------------|------------------------|
| По умолчанию                                                                             | —                      |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | upstream               |

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

#### NOTE
Содержимое зоны сохраняется при перезагрузке только в том случае, если
настроенный `размер` не изменился. Любое изменение — увеличение
или уменьшение — приводит к пересозданию зоны с потерей всех данных.

<a id="index-4"></a>

<a id="s-u-backup-switch"></a>

### backup_switch (PRO)

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `backup_switch` `permanent`[=время];   |
|------------------------------------------------------------------------------------------|----------------------------------------|
| По умолчанию                                                                             | —                                      |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | upstream                               |

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

Если параметр `permanent` определен без значения [времени](https://angie.software//angie/docs/configuration/configfile.md#syntax),
группа остается активной после выбора,
и автоматическая перепроверка групп с меньшим уровнем не происходит.
Если время задано,
то активный статус группы истекает через указанный интервал,
и балансировщик снова проверяет группы с меньшим уровнем,
возвращаясь к ним, если серверы работают нормально.

Пример:

```nginx
upstream media_backend {
    server primary1.example.com:1935;
    server primary2.example.com:1935;

    server reserve1.example.com:1935 backup;
    server reserve2.example.com:1935 backup;

    backup_switch permanent=2m;
}
```

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

<a id="index-5"></a>

<a id="s-u-feedback"></a>

### feedback (PRO)

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `feedback` переменная [`inverse`] [`factor=`число] [`account=`условная_переменная];   |
|------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|
| По умолчанию                                                                             | —                                                                                     |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | upstream                                                                              |

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

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

| `переменная`   | Переменная, из которой берется значение обратной связи.<br/>Она должна представлять собой метрику производительности или состояния;<br/>предполагается, что ее передает сервер.<br/><br/>Значение оценивается при каждом ответе от сервера<br/>и учитывается в скользящем среднем<br/>согласно настройкам `inverse` и `factor`.                                                                                                                                                                                                                                                                                                                                                  |
|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `inverse`      | Если параметр задан, значение обратной связи интерпретируется наоборот:<br/>более низкие значения указывают на лучшую производительность.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `factor`       | Коэффициент, по которому значение обратной связи учитывается<br/>при расчете среднего.<br/>Допустимы целые числа от 0 до 99.<br/>По умолчанию — `90`.<br/><br/>Среднее рассчитывается по формуле [экспоненциального сглаживания](https://ru.wikipedia.org/wiki/Экспоненциальное_сглаживание).<br/><br/>Чем больше коэффициент, тем меньше новые значения влияют на среднее;<br/>если указать `90`, то будет взято 90 % от предыдущего значения<br/>и лишь 10 % от нового.                                                                                                                                                                                                        |
| `account`      | Указывает условную переменную,<br/>которая контролирует, как соединения учитываются при расчете.<br/>Среднее значение обновляется с учетом значения обратной связи,<br/>только если условная переменная<br/>не равна `""` или `"0"`.<br/><br/>#### NOTE<br/>По умолчанию трафик от [активных проверок](https://angie.software//angie/docs/configuration/modules/stream/stream_upstream_probe.md#s-u-upstream-probe)<br/>не включается в расчет;<br/>комбинация переменной [$upstream_probe](https://angie.software//angie/docs/configuration/modules/http/http_upstream_probe.md#v-upstream-probe)<br/>с `account` позволяет включить и их<br/>или даже исключить все остальное. |

Пример:

```nginx
upstream backend {

    zone backend 1m;

    feedback $feedback_value factor=80 account=$condition_value;

    server backend1.example.com:1935  weight=1;
    server backend2.example.com:1935  weight=2;
}

map $protocol $feedback_value {
    "TCP"                      100;
    "UDP"                      75;
    default                    10;
}

map $upstream_probe $condition_value {
    "high_priority" "1";
    "low_priority"  "0";
    default         "1";
}
```

Эта конфигурация категоризирует серверы по уровням обратной связи
на основе протоколов, используемых в отдельных сессиях,
а также добавляет условие на [$upstream_probe](https://angie.software//angie/docs/configuration/modules/http/http_upstream_probe.md#v-upstream-probe),
чтобы учитывать только активную проверку `high_priority`
или обычные клиентские сессии.

<a id="index-6"></a>

<a id="s-u-hash"></a>

### hash

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `hash` ключ [`consistent`];   |
|------------------------------------------------------------------------------------------|-------------------------------|
| По умолчанию                                                                             | —                             |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | upstream                      |

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

Пример использования:

```nginx
hash $remote_addr;
```

При использовании доменных имен, разрешающихся в несколько IP-адресов
(например, с параметром `resolve`),
сервер не сортирует полученные адреса, поэтому их порядок может различаться
на разных серверах, что влияет на распределение клиентов.
Чтобы обеспечить одинаковое распределение,
используйте параметр `consistent`.

Если задан параметр `consistent`, то вместо вышеописанного метода будет
использоваться метод консистентного хэширования [ketama](https://www.metabrew.com/article/libketama-consistent-hashing-algo-memcached-clients).
Метод гарантирует, что при добавлении сервера в группу или его удалении на
другие серверы будет перераспределено минимальное число ключей. Применение
метода для кэширующих серверов обеспечивает больший процент попаданий в кэш.
Метод совместим с библиотекой Perl [Cache::Memcached::Fast](https://metacpan.org/pod/Cache::Memcached::Fast) при значении параметра
`ketama_points`, равном 160.

<a id="index-7"></a>

<a id="s-u-least-conn"></a>

### least_conn

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `least_conn`;   |
|------------------------------------------------------------------------------------------|-----------------|
| По умолчанию                                                                             | —               |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | upstream        |

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

<a id="index-8"></a>

<a id="s-u-least-time"></a>

### least_time (PRO)

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `least_time` `connect` | `first_byte` | `last_byte` [`factor=`number] [`account=`condition_variable];   |
|------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
| По умолчанию                                                                             | —                                                                                                       |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | upstream                                                                                                |

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

| `connect`    | Директива учитывает среднее время установки соединения.            |
|--------------|--------------------------------------------------------------------|
| `first_byte` | Директива использует среднее время получения первого байта ответа. |
| `last_byte`  | Директива использует среднее время получения полного ответа.       |

| `factor`   | Выполняет ту же функцию, что и [response_time_factor (PRO)](#s-u-response-time-factor),<br/>и переопределяет его, если параметр задан.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `account`  | Указывает условную переменную,<br/>которая контролирует, какие соединения учитываются при расчете.<br/>Среднее значение обновляется,<br/>только если условная переменная соединения<br/>не равна `""` или `"0"`.<br/><br/>#### NOTE<br/>По умолчанию [активные проверки](https://angie.software//angie/docs/configuration/modules/http/http_upstream_probe.md#u-upstream-probe)<br/>не включаются в расчет;<br/>комбинация переменной [$upstream_probe](https://angie.software//angie/docs/configuration/modules/http/http_upstream_probe.md#v-upstream-probe)<br/>с `account` позволяет включить их<br/>или даже исключить все остальное. |

Текущие значения представлены как `connect_time`, `first_byte_time`
и `last_byte_time` в объекте `health` сервера
среди [метрик апстрима](https://angie.software//angie/docs/configuration/modules/http/http_api.md#api-status-stream-upstreams) в API.

<a id="index-9"></a>

<a id="s-u-random"></a>

### random

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `random` [`two`];   |
|------------------------------------------------------------------------------------------|---------------------|
| По умолчанию                                                                             | —                   |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | upstream            |

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

Если указан необязательный параметр `two`, Angie случайным образом выбирает два сервера, из которых выбирает сервер, используя указанный метод. Методом по умолчанию является [least_conn](#s-u-least-conn), при котором соединение передается на сервер с наименьшим количеством активных соединений.

<a id="index-10"></a>

<a id="s-u-response-time-factor"></a>

### response_time_factor (PRO)

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `response_time_factor` число;   |
|------------------------------------------------------------------------------------------|---------------------------------|
| По умолчанию                                                                             | `response_time_factor 90;`      |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | upstream                        |

Задает для метода балансировки нагрузки [least_time (PRO)](#s-u-least-time) коэффициент
сглаживания **предыдущего** значения при вычислении среднего времени ответа по формуле
[экспоненциально взвешенного скользящего среднего](https://ru.wikipedia.org/wiki/Скользящая_средняя#Экспоненциально_взвешенное_скользящее_среднее).

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

Текущие результаты вычислений представлены как `connect_time` (время
установления соединения), `first_byte_time` (время получения первого
байта ответа) и `last_byte_time` (время получения ответа целиком) в
объекте `health` сервера среди [метрик апстрима](https://angie.software//angie/docs/configuration/modules/http/http_api.md#api-status-stream-upstreams) в API.

#### NOTE
При подсчете учитываются только успешные ответы; что считать неуспешным
ответом, определяют директивы [proxy_next_upstream](https://angie.software//angie/docs/configuration/modules/stream/stream_proxy.md#s-proxy-next-upstream).

<a id="index-11"></a>

<a id="s-u-sticky"></a>

### sticky

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `sticky route` значение...;<br/><br/>`sticky learn` `zone=`zone `create=`$create_var1... `lookup=`$lookup_var1... [`connect`] [`norefresh`] [`timeout=`time];<br/><br/>`sticky learn` `lookup=`$lookup_var1... `remote_action=`uri `remote_result=`$remote_var [`remote_uri=`uri];   |
|------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| По умолчанию                                                                             | —                                                                                                                                                                                                                                                                                    |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | upstream                                                                                                                                                                                                                                                                             |

Настраивает привязку клиентских сессий к проксируемым серверам
в режиме, заданном первым параметром;
для разгрузки серверов,
у которых задана директива `sticky`,
можно использовать опцию `drain` (PRO) в блоке [server](#s-u-server).

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

Режим `route`

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

Здесь при установлении соединения проксируемый сервер
может назначить клиенту маршрут и вернуть его идентификатор способом,
известным им обоим.
В качестве идентификатора маршрута
должно использоваться значение параметра [sid](#s-reresolve)
директивы [server](#s-u-server).
Учтите, что параметр дополнительно хэшируется,
если задана директива [sticky_secret](#s-u-sticky-secret).

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

В параметрах директивы указываются строки, которые могут содержать
переменные для маршрутизации. Чтобы выбрать сервер, куда направляется
входящее соединение, используется первое непустое значение;
она затем сравнивается с параметром [sid](#s-reresolve)
директивы [server](#s-u-server).
Если выбрать сервер не удается
или выбранный сервер не может принять соединение,
то будет выбран другой сервер
согласно настроенному методу балансировки.

Здесь Angie ищет идентификатор маршрута в переменной `$route`,
получающей значение на основе [$ssl_preread_server_name](https://angie.software//angie/docs/configuration/modules/stream/stream_ssl_preread.md#v-ssl-preread-server-name)
(обратите внимание, что нужно включить [ssl_preread](https://angie.software//angie/docs/configuration/modules/stream/stream_ssl_preread.md#s-ssl-preread)):

```nginx
stream {

    map $ssl_preread_server_name $route {

        a.example.com            a;
        b.example.com            b;
        default                  "";
    }

    upstream backend {

        server 127.0.0.1:8081 sid=a;
        server 127.0.0.1:8082 sid=b;

        sticky route $route;
    }

    server {

        listen 127.0.0.1:8080;

        ssl_preread on;

        proxy_pass backend;
    }
}
```

Режим `learn` (PRO)

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

Здесь сессия создается
на основе свойств соединения, идущих от проксируемого сервера.
С параметрами `create` и `lookup` перечисляются переменные,
указывающие, как создаются новые и ищутся существующие сессии.
Оба параметра можно использовать по нескольку раз.

Идентификатором сессии служит значение первой непустой переменной,
указанной с `create`;
например, это может быть
[имя проксируемого сервера](https://angie.software//angie/docs/configuration/modules/http/index.md#v-server-name).

Сессии хранятся в зоне разделяемой памяти;
ее имя и размер задаются параметром `zone`.
Если к сессии не было обращений в течение [времени](https://angie.software//angie/docs/configuration/configfile.md#syntax)
`timeout`, она удаляется.
Значение по умолчанию — 1 час.

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

Последующие соединения от клиентов, желающих использовать сессию,
должны содержать ее идентификатор.
Параметр `lookup` ищет идентификатор сессии в соединении
по заданному для него списку переменных,
останавливаясь на первой непустой.
Если ничего не найдено — запрос считается новым.
Значение найденного идентификатора
сопоставляется с сессиями в разделяемой памяти.
Если выбрать сервер не удается
или выбранный сервер не может обработать соединение,
то будет выбран другой сервер
согласно настроенному методу балансировки.

Параметр `connect` позволяет создать сессию
сразу после установления соединения с проксируемым сервером.
Без него сессия создается только после завершения обработки соединения.
(В случае UDP-соединений сессии создаются сразу после выбора сервера.)

В примере Angie создает и ищет сессии,
используя переменную [$rdp_cookie](https://angie.software//angie/docs/configuration/modules/stream/stream_rdp_preread.md#v-rdp-cookie):

```nginx
stream {

    upstream backend {

        server 127.0.0.1:3390;
        server 127.0.0.1:3391;

        sticky learn lookup=$rdp_cookie create=$rdp_cookie zone=sessions:1m;
    }

    server {

        listen 127.0.0.1:3389;

        rdp_preread on;

        proxy_pass backend;
    }
}
```

Режим `learn` с `remote_action` (PRO 1.10.0+)

Параметры `remote_action` и `remote_result`
позволяют динамически назначать идентификаторы сессий и управлять ими
с использованием удаленного хранилища сессий (PRO).

В отличие от режима `learn` с `zone`,
данный режим не кэширует сессии локально
и обращается к удаленному хранилищу при каждом соединении.

Параметр `remote_action` должен указывать на `location`
в контексте [client](https://angie.software//angie/docs/configuration/modules/http/index.md#client).
Параметр `remote_uri` задает URI клиентского HTTP-запроса
к указанному `location`.
По умолчанию он равен `/`.
Значение `remote_uri` может содержать переменные.

Общий принцип работы режима таков:
если идентификатор сессии не найден локально,
Angie отправляет синхронный подзапрос в некое удаленное хранилище,
заданное параметром `remote_action`.

При поступлении нового соединения Angie выполняет следующие действия:

- Сначала извлекается идентификатор сессии из первой непустой переменной
  в списке `lookup`.
  Если все переменные пустые,
  используется обычный алгоритм балансировки нагрузки без привязки.
- Затем Angie отправляет в удаленное хранилище,
  заданное параметром `remote_action`, синхронный HTTP-подзапрос,
  который должен содержать в понятном хранилищу виде:
  - идентификатор  *сессии* из параметра `lookup`
    (в конфигурации это переменная
    [$sticky_sessid](#v-s-sticky-sessid));
  - идентификатор предварительно выбранного  *сервера*:
    значение параметра `sid=` из директивы `server`,
    если оно задано,
    либо MD5-хэш имени сервера
    (в конфигурации это переменная
    [$sticky_sid](#v-s-sticky-sid)).

  Переменные `$sticky_sessid` и `$sticky_sid` автоматически
  экспортируются в HTTP-контекст c префиксом `stream_`:
  `$stream_sticky_sessid`, `$stream_sticky_sid`.
  Это позволяет напрямую использовать их в HTTP-директивах,
  например через HTTP-заголовки с помощью [proxy_set_header](https://angie.software//angie/docs/configuration/modules/http/http_proxy.md#proxy-set-header).
- Удаленное хранилище обрабатывает запрос и возвращает HTTP-ответ:

  Ответ с кодом 200, 201 или 204 подтверждает выбранный сервер.
  Удаленное хранилище может одновременно с этим
  вернуть альтернативный идентификатор сервера в HTTP-заголовке
  или в теле ответа (PRO); извлечь его можно через `remote_result`.

  При получении от хранилища любого другого HTTP-кода
  (включая ошибки сети и таймауты)
  либо несуществующего идентификатора сервера
  Angie использует изначально выбранный сервер.

Идентификатор сервера извлекается из ответа удаленного хранилища
через параметр `remote_result`:
в нем можно указывать переменные
с префиксом `upstream_http_`,
которые создаются Angie автоматически для доступа
к заголовкам HTTP-ответов от удаленного хранилища,
или [$sent_body](https://angie.software//angie/docs/configuration/modules/http/index.md#v-sent-body) для использования тела ответа.
Например, заголовок `X-Sid: server1` в таком ответе
становится доступным в переменной `$upstream_http_x_sid`
со значением `server1`.

Ниже показан упрощенный пример конфигурации.
Удаленное хранилище возвращает идентификатор сервера в заголовке `X-Sticky-Sid`
и таким образом подтверждает или переопределяет выбор Angie:

```nginx
http {

    client {

        location @sticky_client1 {

            # используем переменные из потокового upstream;
            # он добавляет эти переменные в HTTP-контекст с префиксом stream_*
            proxy_set_header X-Sticky-Sessid $stream_sticky_sessid;
            proxy_set_header X-Sticky-Sid $stream_sticky_sid;
            proxy_set_header X-Sticky-Last $msec;
            proxy_pass http://127.0.0.1:8080;

            proxy_cache remote;
            proxy_cache_valid 200 1d;
            proxy_cache_key $scheme$proxy_host$request_uri$stream_sticky_sessid;
        }
    }
}

stream {

    upstream u {

        server 127.0.0.1:8081 sid=backend-01;
        server 127.0.0.1:8082 sid=backend-02;

        sticky learn lookup=$remote_addr            # переменная stream
        remote_action=@sticky_client1               # location из блока client
        remote_result=$upstream_http_x_sticky_sid   # HTTP-переменная
        remote_uri=/foo;                            # по умолчанию - /
    }

    server {

        listen 127.0.0.1:8080;
        proxy_pass u;
    }
}
```

Здесь при следующем ответе от удаленного хранилища:

```none
HTTP/1.1 200 OK
...
X-Sticky-Sid: backend-01
X-Session-Info: active
```

Становятся доступными две переменные:

- `$upstream_http_x_sticky_sid`,
  со значением `backend-01`;
- `$upstream_http_x_session_info`,
  со значением `active`.

Так как переменная `$upstream_http_x_sticky_sid`
указана в параметре `remote_result`,
то ее значение будет использовано
для выбора сервера с `sid=backend-01`.

Директива `sticky` учитывает состояние серверов в [upstream](#s-u-upstream):

- Cерверы, помеченные как `down` или временно недоступные из-за сбоев,
  исключаются из выбора.
- Cерверы, которые достигли максимального количества соединений
  (при использовании `max_conns`), временно пропускаются.
- Cерверы с опцией `drain` (PRO)
  могут быть выбраны для создания новых сессий в режиме `sticky`
  при совпадении идентификаторов.
- Если ранее недоступный сервер восстанавливается,
  `sticky` автоматически возобновляет его использование.

Поведение `sticky` можно дополнительно настроить
директивами [sticky_secret](#s-u-sticky-secret) и [sticky_strict](#s-u-sticky-strict).
Если в ходе работы `sticky` выбрать сервер не удается или он недоступен,
запрос будет обработан согласно выбранному методу балансировки нагрузки,
если только не включена директива `sticky_strict`.
В режиме `sticky_strict on;` запрос отклоняется с ошибкой.

Зоны разделяемой памяти,
указываемые в параметре `zone` директивы `sticky`,
не могут использоваться совместно различными `upstream`;
каждая группа должна использовать свою собственную зону.

<a id="index-12"></a>

<a id="s-u-sticky-secret"></a>

### sticky_secret

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `sticky_secret` строка;   |
|------------------------------------------------------------------------------------------|---------------------------|
| По умолчанию                                                                             | —                         |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | upstream                  |

Добавляет строку как соль в функцию MD5-хэширования
для директивы [sticky](#s-u-sticky) в режиме `route`.
Строка может содержать переменные, например `$remote_addr`:

```nginx
upstream backend {
    server 127.0.0.1:8081 sid=a;
    server 127.0.0.1:8082 sid=b;

    sticky route $route;
    sticky_secret my_secret.$remote_addr;
}
```

Соль добавляется после хэшируемого значения;
чтобы независимо проверить механизм хэширования:

```console
$ echo -n "<VALUE><SALT>" | md5sum
```

<a id="index-13"></a>

<a id="s-u-sticky-strict"></a>

### sticky_strict

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `sticky_strict` `on` | `off`;   |
|------------------------------------------------------------------------------------------|---------------------------------|
| По умолчанию                                                                             | `sticky_strict off;`            |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | upstream                        |

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

<a id="built-in-variables-25"></a>

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

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

<a id="v-s-sticky-sessid"></a>

### `$sticky_sessid`

Используется с `remote_action` в [sticky](#s-u-sticky);
хранит начальный идентификатор сессии, взятый из `lookup`.

<a id="v-s-sticky-sid"></a>

### `$sticky_sid`

Используется с `remote_action` в [sticky](#s-u-sticky);
хранит идентификатор сервера, предварительно связанный с сессией.

В `sticky_sid` содержится значение параметра `sid=`
из блока [upstream](#s-u-upstream) директивы `server`, если оно задано,
либо MD5-хэш имени сервера.

<a id="v-s-upstream-addr"></a>

### `$upstream_addr`

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

> 192.168.1.1:1935, 192.168.1.2:1935, unix:/tmp/sock"

Если сервер не может быть выбран, то переменная хранит имя [группы серверов](#s-u-upstream).

<a id="v-s-upstream-bytes-received"></a>

### `$upstream_bytes_received`

число байт, полученных от сервера группы. Значения нескольких соединений разделяются запятыми и двоеточиями подобно адресам в переменной [$upstream_addr](#v-s-upstream-addr).

<a id="v-s-upstream-bytes-sent"></a>

### `$upstream_bytes_sent`

число байт, переданных на сервер группы. Значения нескольких соединений разделяются запятыми и двоеточиями подобно адресам в переменной [$upstream_addr](#v-s-upstream-addr).

<a id="v-s-upstream-connect-time"></a>

### `$upstream_connect_time`

хранит время, затраченное на установление соединения с сервером группы; время хранится в секундах с точностью до миллисекунд. Времена нескольких соединений разделяются запятыми и двоеточиями подобно адресам в переменной [$upstream_addr](#v-s-upstream-addr).

<a id="v-s-upstream-first-byte-time"></a>

### `$upstream_first_byte_time`

время получения первого байта данных; время хранится в секундах с точностью до миллисекунд. Времена нескольких соединений разделяются запятыми подобно адресам в переменной [$upstream_addr](#v-s-upstream-addr).

<a id="v-s-upstream-session-time"></a>

### `$upstream_session_time`

длительность сессии в секундах с точностью до миллисекунд. Времена нескольких соединений разделяются запятыми подобно адресам в переменной [$upstream_addr](#v-s-upstream-addr).

<a id="v-s-upstream-sticky-status"></a>

### `$upstream_sticky_status`

Статус соединений с привязкой.

| `""`   | Соединение направлено в группу серверов, где привязка не используется.                |
|--------|---------------------------------------------------------------------------------------|
| `NEW`  | Соединение не содержит информации о привязке к серверу.                               |
| `HIT`  | Соединение с привязкой направлено на желаемый сервер.                                 |
| `MISS` | Соединение с привязкой направлено на сервер,<br/>выбранный по алгоритму балансировки. |

Статусы из нескольких соединений разделяются запятыми и двоеточиями
аналогично адресам в переменной [$upstream_addr](https://angie.software//angie/docs/configuration/modules/http/http_upstream.md#v-upstream-addr).
