Балансировка нагрузки TCP и UDP
В этой главе описывается, как использовать NGINX Plus и NGINX с открытым исходным кодом для проксирования и балансировки нагрузки трафика TCP и UDP.
Введение
Балансировка нагрузки относится к эффективному распределению сетевого трафика между несколькими внутренними серверами.
В NGINX Plus Release 5 и более поздних версиях NGINX Plus может проксировать и балансировать трафик протокола управления передачей (TCP). TCP — это протокол для многих популярных приложений и служб, таких как LDAP, MySQL и RTMP.
В NGINX Plus Release 9 и более поздних версиях NGINX Plus может проксировать и балансировать нагрузку UDP-трафика. UDP (протокол пользовательских дейтаграмм) — это протокол для многих популярных нетранзакционных приложений, таких как DNS, системный журнал и RADIUS.
Чтобы сбалансировать нагрузку HTTP-трафика, обратитесь к статье Балансировка нагрузки HTTP .
Предпосылки
- Последний NGINX Plus (дополнительные этапы сборки не требуются) или последний NGINX с открытым исходным кодом , созданный с
--with-stream
флагом конфигурации - Приложение, база данных или служба, которые взаимодействуют через TCP или UDP.
- Серверы восходящего потока, на каждом из которых работает один и тот же экземпляр приложения, базы данных или службы.
Настройка обратного прокси
Во-первых, вам нужно настроить обратный прокси -сервер , чтобы NGINX Plus или NGINX с открытым исходным кодом могли пересылать TCP-соединения или дейтаграммы UDP от клиентов в вышестоящую группу или на прокси-сервер.
Откройте файл конфигурации NGINX и выполните следующие действия:
Создайте блок верхнего уровня stream {}
:
stream {
# ...
}
Определите один или несколько блоков конфигурации для каждого виртуального сервера в контексте server {}
верхнего уровня .stream {}
В server {}
блоке конфигурации для каждого сервера включите listen
директиву для определения IP-адреса и/или порта , который прослушивает сервер.
Для трафика UDP также включите этот udp
параметр. Поскольку TCP является протоколом по умолчанию для контекста, в директиве stream
нет tcp
параметра :listen
stream {
server {
listen 12345;
# ...
}
server {
listen 53 udp;
# ...
}
# ...
}
Включите proxy_pass
директиву для определения прокси-сервера или вышестоящей группы, на которую сервер перенаправляет трафик:
stream {
server {
listen 12345;
#TCP traffic will be forwarded to the "stream_backend" upstream group
proxy_pass stream_backend;
}
server {
listen 12346;
#TCP traffic will be forwarded to the specified server
proxy_pass backend.example.com:12346;
}
server {
listen 53 udp;
#UDP traffic will be forwarded to the "dns_servers" upstream group
proxy_pass dns_servers;
}
# ...
}
Если прокси-сервер имеет несколько сетевых интерфейсов, вы можете дополнительно настроить NGINX на использование определенного исходного IP-адреса при подключении к вышестоящему серверу. Это может быть полезно, если прокси-сервер за NGINX настроен на прием соединений из определенных IP-сетей или диапазонов IP-адресов.
Включите proxy_bind
директиву и IP-адрес соответствующего сетевого интерфейса:
stream {
# ...
server {
listen 127.0.0.1:12345;
proxy_pass backend.example.com:12345;
proxy_bind 127.0.0.1:12345;
}
}
При желании вы можете настроить размер двух буферов в памяти, куда NGINX может помещать данные как от клиентских, так и от вышестоящих подключений. При небольшом объеме данных буферы можно уменьшить, что может сэкономить ресурсы памяти. Если имеется большой объем данных, размер буфера можно увеличить, чтобы уменьшить количество операций чтения/записи сокета. Как только данные получены по одному соединению, NGINX считывает их и пересылает по другому соединению. Буферы управляются proxy_buffer_size
директивой:
stream {
# ...
server {
listen 127.0.0.1:12345;
proxy_pass backend.example.com:12345;
proxy_buffer_size 16k;
}
}
Настройка балансировки нагрузки TCP или UDP
Чтобы настроить балансировку нагрузки:
Создайте группу серверов или восходящую группу , трафик которой будет сбалансирован по нагрузке. Определите один или несколько upstream {}
блоков конфигурации в контексте верхнего уровня stream {}
и задайте имя для вышестоящей группы, например, stream_backend
для серверов TCP и dns_servers
для серверов UDP:
stream {
upstream stream_backend {
# ...
}
upstream dns_servers {
# ...
}
# ...
}
Убедитесь, что на имя вышестоящей группы ссылается proxy_pass
директива, подобная настроенной выше для обратного прокси.
Заполните восходящую группу вышестоящими серверами . Внутри upstream {}
блока добавьте server
директиву для каждого вышестоящего сервера, указав его IP-адрес или имя хоста (которое может разрешаться в несколько IP-адресов) и обязательный номер порта. Обратите внимание, что вы не определяете протокол для каждого сервера, потому что он определяется для всей восходящей группы параметром, который вы включаете в listen
директиву в server
блоке, который вы создали ранее .
stream {
upstream stream_backend {
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12346;
# ...
}
upstream dns_servers {
server 192.168.136.130:53;
server 192.168.136.131:53;
# ...
}
# ...
}
Настройте метод балансировки нагрузки, используемый вышестоящей группой. Вы можете указать один из следующих методов:
Round Robin — по умолчанию NGINX использует алгоритм Round Robin для балансировки нагрузки трафика, последовательно направляя его на серверы в настроенной вышестоящей группе. Поскольку это метод по умолчанию, round?robin
директивы нет; просто создайте блок конфигурации в контексте upstream {}
верхнего уровня и добавьте директивы, как описано в предыдущем шаге.stream {}server
Наименьшее количество подключений — NGINX выбирает сервер с наименьшим количеством текущих активных подключений.
Наименьшее время (только NGINX Plus) — NGINX Plus выбирает сервер с наименьшей средней задержкой и наименьшим количеством активных подключений. Метод, используемый для расчета наименьшей средней задержки, зависит от того, какой из следующих параметров включен в least_time
директиву:
connect
– Время подключения к вышестоящему серверуfirst_byte
– Время приема первого байта данныхlast_byte
– Время получения полного ответа от сервера
Хэш — NGINX выбирает сервер на основе заданного пользователем ключа, например, исходного IP-адреса ( $remote_addr
):
upstream stream_backend {
hash $remote_addr;
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12346;
}
Метод Hash
балансировки нагрузки также используется для настройки сохраняемости сеанса . Поскольку хеш-функция основана на IP-адресе клиента, соединения от данного клиента всегда передаются на один и тот же сервер, если только сервер не отключен или недоступен по другой причине. Укажите необязательный consistent
параметр, чтобы применить метод последовательного хеширования ketama :
hash $remote_addr consistent;
Случайный — каждое соединение будет передаваться на случайно выбранный сервер. Если two
параметр указан, то сначала NGINX случайным образом выбирает два сервера с учетом весов серверов, а затем выбирает один из этих серверов указанным методом:
least_conn
– Наименьшее количество активных подключенийleast_time=connect
(NGINX Plus) — время подключения к вышестоящему серверу ($upstream_connect_time
)least_time=first_byte
(NGINX Plus) — наименьшее среднее время получения первого байта данных с сервера ($upstream_first_byte_time
)least_time=last_byte
(NGINX Plus) — наименьшее среднее время получения последнего байта данных с сервера ($upstream_session_time
)
При необходимости для каждого вышестоящего сервера укажите параметры, специфичные для сервера, включая максимальное количество подключений , вес сервера и т. д.:
upstream stream_backend {
hash $remote_addr consistent;
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345;
server backend3.example.com:12346 max_conns=3;
}
upstream dns_servers {
least_conn;
server 192.168.136.130:53;
server 192.168.136.131:53;
# ...
}
Альтернативный подход заключается в том, чтобы проксировать трафик на один сервер, а не на вышестоящую группу. Если вы идентифицируете сервер по имени хоста и настроите имя хоста для разрешения нескольких IP-адресов, то NGINX распределяет трафик по IP-адресам с помощью Round Robin
алгоритма. В этом случае вы должны указать номер порта сервера в proxy_pass
директиве и не должны указывать протокол перед IP-адресом или именем хоста:
stream {
# ...
server {
listen 12345;
proxy_pass backend.example.com:12345;
}
}
Настройка проверок работоспособности
NGINX может постоянно тестировать вышестоящие TCP- или UDP-серверы, избегать отказавших серверов и корректно добавлять восстановленные серверы в группу с балансировкой нагрузки.
Инструкции по настройке проверок работоспособности для TCP см. в разделе Проверки работоспособности TCP.
Инструкции по настройке проверок работоспособности для UDP см. в разделе Проверки работоспособности UDP.
Конфигурация «на лету»
Группы вышестоящих серверов можно легко перенастроить «на лету» с помощью NGINX Plus REST API. Используя этот интерфейс, вы можете просматривать все серверы в вышестоящей группе или отдельном сервере, изменять параметры сервера, а также добавлять или удалять вышестоящие серверы.
Чтобы включить настройку «на лету»:
Создайте блок верхнего уровня http {}
или убедитесь, что он присутствует в вашей конфигурации:
http {
# ...
}
Создайте место для запросов конфигурации, например, api :
http {
server {
location /api {
# ...
}
}
}
В этом месте укажите api
директиву:
http {
server {
location /api {
api;
# ...
}
}
}
По умолчанию API NGINX Plus предоставляет доступ к данным только для чтения. Параметр write=on
разрешает доступ для чтения/записи, чтобы можно было вносить изменения в восходящие потоки:
http {
server {
location /api {
api write=on;
# ...
}
}
}
Ограничьте доступ к этому местоположению с помощью директив allow
и :deny
http {
server {
location /api {
api write=on;
allow 127.0.0.1; # permit access from localhost
deny all; # deny access from everywhere else
}
}
}
Когда API включен в режиме записи, рекомендуется ограничить доступ к PATCH
, POST
и DELETE
методам для определенных пользователей. Это можно сделать, внедрив базовую аутентификацию HTTP :
http {
server {
location /api {
limit_except GET {
auth_basic "NGINX Plus API";
auth_basic_user_file /path/to/passwd/file;
}
api write=on;
allow 127.0.0.1;
deny all;
}
}
}
Создайте зону общей памяти для группы вышестоящих серверов, чтобы все рабочие процессы могли использовать одну и ту же конфигурацию. Для этого в stream {}
блоке верхнего уровня находим целевую группу upsteam, добавляем zone
директиву в группу upstream server и указываем имя зоны (здесь stream_backend ) и объем памяти (64 КБ):
stream {
upstream stream_backend {
zone backend 64k;
# ...
}
}
Пример конфигурации «на лету»
stream {
# ...
# Configuration of an upstream server group
upstream appservers {
zone appservers 64k;
server appserv1.example.com:12345 weight=5;
server appserv2.example.com:12345 fail_timeout=5s;
server backup1.example.com:12345 backup;
server backup2.example.com:12345 backup;
}
server {
# Server that proxies connections to the upstream group
proxy_pass appservers;
health_check;
}
}
http {
# ...
server {
# Location for API requests
location /api {
limit_except GET {
auth_basic "NGINX Plus API";
auth_basic_user_file /path/to/passwd/file;
}
api write=on;
allow 127.0.0.1;
deny all;
}
}
}
Здесь доступ к местоположению разрешен только с адреса локального хоста ( 127.0.0.1
). Доступ со всех других IP-адресов запрещен.
Чтобы передать конфигурационную команду в NGINX, отправьте API-команду любым способом, например, с помощью curl.
Например, чтобы добавить новый сервер в группу серверов, отправьте POST
запрос:
curl -X POST -d '{ \
"server": "appserv3.example.com:12345", \
"weight": 4 \
}' -s 'http://127.0.0.1/api/6/stream/upstreams/appservers/servers'
Чтобы удалить сервер из группы серверов, отправьте DELETE
запрос:
curl -X DELETE -s 'http://127.0.0.1/api/6/stream/upstreams/appservers/servers/0'
Чтобы изменить параметр для конкретного сервера, отправьте PATCH
запрос:
curl -X PATCH -d '{ "down": true }' -s 'http://127.0.0.1/api/6/http/upstreams/appservers/servers/0'
Пример конфигурации балансировки нагрузки TCP и UDP
Это пример конфигурации балансировки нагрузки TCP и UDP с NGINX:
stream {
upstream stream_backend {
least_conn;
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345 max_fails=2 fail_timeout=30s;
server backend3.example.com:12345 max_conns=3;
}
upstream dns_servers {
least_conn;
server 192.168.136.130:53;
server 192.168.136.131:53;
server 192.168.136.132:53;
}
server {
listen 12345;
proxy_pass stream_backend;
proxy_timeout 3s;
proxy_connect_timeout 1s;
}
server {
listen 53 udp;
proxy_pass dns_servers;
}
server {
listen 12346;
proxy_pass backend4.example.com:12346;
}
}
В этом примере вся функциональность, связанная с прокси-сервером TCP и UDP, настраивается внутри stream
блока точно так же, как в блоке настраиваются параметры HTTP-запросов http
.
Есть два именованных upstream
блока, каждый из которых содержит три сервера, на которых размещается одинаковый контент. Для server
каждого сервера за именем сервера следует обязательный номер порта. Подключения распределяются между серверами по методу балансировки нагрузки Least Connections : подключение идет к серверу с наименьшим количеством активных подключений.
Три server
блока определяют три виртуальных сервера:
Первый сервер прослушивает порт 12345 и проксирует все TCP-подключения к группе stream_backend вышестоящих серверов. Обратите внимание, что proxy_pass
директива, определенная в контексте stream
модуля, не должна содержать протокол.
Задаются два необязательных параметра таймаута: proxy_connect_timeout
директива задает таймаут, необходимый для установления соединения с сервером в группе stream_backend . Директива proxy_timeout
устанавливает тайм-аут, используемый после запуска проксирования на один из серверов в группе stream_backend .
Второй сервер прослушивает порт 53 и передает все дейтаграммы UDP ( udp
параметр listen
директивы) вышестоящей группе с именем dns_servers . Если udp
параметр не указан, сокет прослушивает соединения TCP.
Третий виртуальный сервер прослушивает порт 12346 и проксирует TCP-подключения к backend4.example.com , которые могут разрешаться в несколько IP-адресов с балансировкой нагрузки с помощью метода Round Robin.
Только полноправные пользователи могут оставлять комментарии. Аутентифицируйтесь пожалуйста, используя сервисы.