Модуль ngx_stream_upstream_module

Пример конфигурации
Директивы
     upstream
     server
     zone
     state
     hash
     least_conn
     least_time
     health_check
     health_check_timeout
     match
Встроенные переменные

Модуль ngx_stream_upstream_module (1.9.0) позволяет описывать группы серверов, которые могут использоваться в директиве proxy_pass.

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

upstream backend {
    hash $remote_addr consistent;

    server backend1.example.com:12345  weight=5;
    server backend2.example.com:12345;
    server unix:/tmp/backend3;

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

server {
    listen 12346;
    proxy_pass backend;
}

Динамически настраиваемая группа, доступна как часть коммерческой подписки:

resolver 10.0.0.1;

upstream dynamic {
    zone upstream_dynamic 64k;

    server backend1.example.com:12345 weight=5;
    server backend2.example.com:12345 fail_timeout=5s slow_start=30s;
    server 192.0.2.1:12345            max_fails=3;
    server backend3.example.com:12345 resolve;
    server backend4.example.com       service=http resolve;

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

server {
    listen 12346;
    proxy_pass dynamic;
    health_check;
}

Директивы

Синтаксис: upstream название { ... }
Умолчание:
Контекст: stream

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

Пример:

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

    server backup1.example.com:12345  backup;
}

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

Синтаксис: server адрес [параметры];
Умолчание:
Контекст: upstream

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

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

weight=число
задаёт вес сервера, по умолчанию 1.
max_conns=число
ограничивает максимальное число одновременных соединений к проксируемому серверу (1.11.5). Значение по умолчанию равно 0 и означает, что ограничения нет. Если группа не находится в зоне разделяемой памяти, то ограничение работает отдельно для каждого рабочего процесса.
До версии 1.11.5 этот параметр был доступен как часть коммерческой подписки.
max_fails=число
задаёт число неудачных попыток работы с сервером, которые должны произойти в течение времени, заданного параметром fail_timeout, чтобы сервер считался недоступным на период времени, также заданный параметром fail_timeout. По умолчанию число попыток устанавливается равным 1. Нулевое значение отключает учёт попыток. В данном случае неудачной попыткой считается ошибка или таймаут при установке соединения с сервером.
fail_timeout=время
задаёт
  • время, в течение которого должно произойти заданное число неудачных попыток работы с сервером для того, чтобы сервер считался недоступным;
  • и время, в течение которого сервер будет считаться недоступным.
По умолчанию параметр равен 10 секундам.
backup
помечает сервер как запасной сервер. На него будут передаваться соединения в случае, если не работают основные серверы.
down
помечает сервер как постоянно недоступный.

Кроме того, следующие параметры доступны как часть коммерческой подписки:

resolve
отслеживает изменения IP-адресов, соответствующих доменному имени сервера, и автоматически изменяет конфигурацию группы без необходимости перезапуска nginx. Группа должна находиться в зоне разделяемой памяти.

Для работы этого параметра директива resolver должна быть задана в блоке stream. Пример:

stream {
    resolver 10.0.0.1;

    upstream u {
        zone ...;
        ...
        server example.com:12345 resolve;
    }
}

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

Если имя сервиса не содержит точку (“.”), то имя составляется в соответствии с RFC и в префикс службы добавляется протокол TCP. Например, для получения SRV-записи _http._tcp.backend.example.com необходимо указать директиву:

server backend.example.com service=http resolve;

Если имя сервиса содержит одну и более точек, то имя составляется при помощи соединения префикса службы и имени сервера. Например, для получения SRV-записей _http._tcp.backend.example.com и server1.backend.example.com необходимо указать директивы:

server backend.example.com service=_http._tcp resolve;
server example.com service=server1.backend resolve;

SRV-записи с наивысшим приоритетом (записи с одинаковым наименьшим значением приоритета) преобразуются в основные серверы, остальные SRV-записи преобразуются в запасные серверы. Если в конфигурации сервера указан параметр backup, высокоприоритетные SRV-записи преобразуются в запасные серверы, остальные SRV-записи игнорируются.

slow_start=время
задаёт время, в течение которого вес сервера восстановится от нуля до своего номинального значения в ситуации, когда неработоспособный (unhealthy) сервер вновь становится работоспособным (healthy) или когда сервер становится доступным по прошествии времени, в течение которого он считался недоступным. Значение по умолчанию равно нулю и означает, что медленный старт выключен.
Параметр нельзя использовать совместно с методом балансировки нагрузки hash.

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

Синтаксис: zone имя [размер];
Умолчание:
Контекст: upstream

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

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

Синтаксис: state файл;
Умолчание:
Контекст: upstream

Эта директива появилась в версии 1.9.7.

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

Примеры:

state /var/lib/nginx/state/servers.conf; # путь для Linux
state /var/db/nginx/state/servers.conf;  # путь для FreeBSD

В данный момент состояние ограничено списком серверов с их параметрами. Файл читается при парсинге конфигурации и обновляется каждый раз при изменении конфигурации группы. Изменение содержимого файла напрямую не рекомендуется. Директиву нельзя использовать совместно с директивой server.

Изменения, совершённые в момент перезагрузки конфигурации или обновления бинарного файла, могут быть потеряны.

Эта директива доступна как часть коммерческой подписки.

Синтаксис: hash ключ [consistent];
Умолчание:
Контекст: upstream

Задаёт метод балансировки нагрузки для группы, при котором соответствие клиента серверу определяется при помощи хэшированного значения ключа. В качестве ключа может использоваться текст, переменные и их комбинации (1.11.2). Пример использования:

hash $remote_addr;

Следует отметить, что любое добавление или удаление серверов в группе может привести к перераспределению большинства ключей на другие серверы. Метод совместим с библиотекой Perl Cache::Memcached.

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

Синтаксис: least_conn;
Умолчание:
Контекст: upstream

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

Синтаксис: least_time connect | first_byte | last_byte;
Умолчание:
Контекст: upstream

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

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

Эта директива доступна как часть коммерческой подписки.

Синтаксис: health_check [параметры];
Умолчание:
Контекст: server

Активирует периодические проверки работоспособности серверов в группе.

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

interval=время
задаёт интервал между двумя последовательными проверками, по умолчанию 5 секунд.
jitter=время
задаёт время, в пределах которого случайным образом задерживается каждая проверка, по умолчанию задержки нет.
fails=число
задаёт число последовательных неуспешных проверок для определённого сервера, после которых сервер будет считаться неработоспособным, по умолчанию 1.
passes=число
задаёт число последовательных успешных проверок для определённого сервера, после которых сервер будет считаться работоспособным, по умолчанию 1.
match=имя
указывает на блок match с условиями, которым должно удовлетворять соединение, чтобы результат проверки считался успешным. По умолчанию проверяется лишь возможность установки TCP-соединения с сервером.
port=число
задаёт порт, используемый при подключении к серверу для проверки его работоспособности (1.9.7). По умолчанию совпадает с портом сервера.
udp
указывает, что для проверки работоспособности будет использоваться протокол UDP вместо протокола TCP, используемого по умолчанию (1.9.13); требует наличия блока match с параметрами send и expect.

В примере

server {
    proxy_pass backend;
    health_check;
}

для каждого сервера группы backend с интервалом в 5 секунд проверяется возможность установки TCP-соединения. Если соединение с сервером не может быть установлено, проверка считается неуспешной и сервер признаётся неработоспособным. На неработоспособные серверы клиентские соединения передаваться не будут.

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

Группа должна находиться в зоне разделяемой памяти.

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

Эта директива доступна как часть коммерческой подписки.

Синтаксис: health_check_timeout время;
Умолчание:
health_check_timeout 5s;
Контекст: stream, server

Переопределяет значение proxy_timeout для проверок работоспособности.

Эта директива доступна как часть коммерческой подписки.

Синтаксис: match имя { ... }
Умолчание:
Контекст: stream

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

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

send строка;
отправляет строку на сервер;
expect стока | ~ regex;
текстовая строка (1.9.12) или регулярное выражение, которым должны соответствовать данные, полученные с сервера. Регулярное выражение задаётся либо с модификатором “~*” (для поиска совпадения без учёта регистра символов), либо с модификатором “~” (с учётом регистра).

Параметры send и expect могут содержать строки в шестнадцатеричном виде с префиксом “\x” и последующими двумя шестнадцатеричными цифрами, например “\x80” (1.9.12).

Проверка работоспособности считается успешной, если

Пример:

upstream backend {
    zone     upstream_backend 10m;
    server   127.0.0.1:12345;
}

match http {
    send     "GET / HTTP/1.0\r\nHost: localhost\r\n\r\n";
    expect ~ "200 OK";
}

server {
    listen       12346;
    proxy_pass   backend;
    health_check match=http;
}

Проверяются лишь первые байты данных proxy_buffer_size, полученные от сервера.

Эта директива доступна как часть коммерческой подписки.

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

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

$upstream_addr
хранит IP-адрес и порт или путь к UNIX-сокету сервера группы (1.11.4). Если при проксировании были сделаны обращения к нескольким серверам, то их адреса разделяются запятой, например “192.168.1.1:12345, 192.168.1.2:12345, unix:/tmp/sock”.
$upstream_bytes_sent
число байт, переданных на сервер группы (1.11.4). Значения нескольких соединений разделяются запятыми подобно адресам в переменной $upstream_addr.
$upstream_bytes_received
число байт, полученных от сервера группы (1.11.4). Значения нескольких соединений разделяются запятыми подобно адресам в переменной $upstream_addr.
$upstream_connect_time
время установки соединения с сервером группы (1.11.4); время хранится в секундах с точностью до миллисекунд. Времена нескольких соединений разделяются запятыми подобно адресам в переменной $upstream_addr.
$upstream_first_byte_time
время получения первого байта данных (1.11.4); время хранится в секундах с точностью до миллисекунд. Времена нескольких соединений разделяются запятыми подобно адресам в переменной $upstream_addr.
$upstream_session_time
длительность сессии в секундах с точностью до миллисекунд (1.11.4). Времена нескольких соединений разделяются запятыми подобно адресам в переменной $upstream_addr.