NGINX: превышено ограничение на 65535 подключений

В отличие от HTTP, веб-сокет сохраняет долговременное соединение после обновления с HTTP.

Даже если ОС настроена на использование всех портов, всего портов всего 65536. Может ли NGINX превысить этот предел?

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

В выпуске NGINX 1.9.1 представлена ​​новая функция, позволяющая использовать параметр сокета SO_REUSEPORT, который доступен в новых версиях многих операционных систем, включая DragonFly BSD и Linux (версия ядра 3.9 и выше). Эта опция сокета позволяет нескольким сокетам прослушивать один и тот же IP-адрес и комбинацию портов. Затем ядро ​​распределяет нагрузку на входящие соединения через сокеты.

Итак, NGINX вызывает accept, чтобы принять входящее соединение.

Системный вызов accept() используется с типами сокетов на основе соединения (SOCK_STREAM, SOCK_SEQPACKET). Он извлекает первый запрос на соединение из очереди ожидающих соединений для слушающего сокета, sockfd, создает новый подключенный сокет и возвращает новый файловый дескриптор, ссылающийся на этот сокет. Вновь созданный сокет не находится в состоянии прослушивания. Исходный сокет sockfd не затрагивается этим вызовом.

Будет ли новый сокет потреблять порт? Если да, то как превысить ограничение в 65535 подключений?


person Mr.Wang from Next Door    schedule 04.12.2015    source источник
comment
Соединения TCP определяются 4-кортежем (src_addr, src_port, dst_addr, dst_port). У вас может быть сервер, подключенный к более чем 65536 клиентам на одном и том же порту, если клиенты используют разные IP-адреса и/или исходные порты. Пример: IP-адрес сервера 0.0.0.1 прослушивает порт 80. Тогда все 4 кортежа могут быть (*, *, 0.0.0.1, 80). Пока нет одинаковых 4-кортежей, сервер может иметь столько подключений к порту 80, сколько позволяет его память.   -  person Cornstalks    schedule 04.12.2015
comment
спасибо, я обновил вопрос, чтобы быть более ясным. Значит, новый сокет, созданный accept, не использует другой порт?   -  person Mr.Wang from Next Door    schedule 04.12.2015
comment
Нет, он не переключается на использование другого порта.   -  person Cornstalks    schedule 04.12.2015
comment
спасибо за согласие, +1 за ваш вопрос; Могу ли я также получить один за мой ответ?   -  person cnst    schedule 11.07.2016


Ответы (1)


Комментарий, который вы получили, правильный:

TCP-соединения определяются четырьмя кортежами (src_addr, src_port, dst_addr, dst_port). У вас может быть сервер, подключенный к более чем 65536 клиентам на одном и том же порту, если клиенты используют разные IP-адреса и/или исходные порты. Пример: IP-адрес сервера 0.0.0.1 прослушивает порт 80. Тогда все 4 кортежа могут быть (*, *, 0.0.0.1, 80). Пока нет одинаковых 4-кортежей, сервер может иметь столько подключений к порту 80, сколько позволяет его память. — Кукурузные стебли

Однако при оценке того, превысите ли вы ограничения, вы также должны учитывать, что nginx — это не просто сервер (имеющий ngx_connection.c#ngx_open_listening_sockets() вызов socket(2), bind(2) и listen(2) для захвата таких портов, как 80, и последующий вызов accept(2) в бесконечном цикле), но он также потенциально является клиентом вышестоящего сервера. (вызов socket(2) и connect(2) для подключения к восходящим потокам через такие порты, как 8080, по мере необходимости).

Обратите внимание, что исчерпание TCP-портов невозможно для контекста сервера (поскольку сервер использует один и тот же порт для всех своих подключений — например, порт 80), исчерпание TCP-портов на стороне клиента — это реальная проблема. возможность, в зависимости от конфигурации. Вы также должны учитывать, что после того, как клиент выполнит close(2) в соединении, состояние становится равным TIME_WAIT на период в несколько 60 с или около того (чтобы убедиться, что если какие-либо запоздалые пакеты все же пройдут, система будет знать, что с ними делать).

Однако при этом обратите внимание, что опция SO_REUSEPORT для getsockopt(2), по крайней мере, в контекст сегментирования, представленный в упомянутых примечаниях к выпуску и reuseport анонс nginx 1.9.1 совершенно не связан с дилеммой 65535 — это просто строительный блок масштабируемой многопроцессорной поддержки между ядром и приложениями. которые работают под ядром:

Я провел тест wrk с 4 рабочими процессами NGINX на 36-ядерном экземпляре AWS. Чтобы устранить сетевые эффекты, я запустил и клиент, и NGINX на локальном хосте, а также заставил NGINX вернуть строку OK вместо файла. Я сравнил три конфигурации NGINX: по умолчанию (эквивалентно включенному accept_mutex), с выключенным accept_mutex и с повторным использованием порта. Как показано на рисунке, повторное использование порта увеличивает количество запросов в секунду в 2–3 раза и снижает как задержку, так и стандартное отклонение задержки.

Тестирование повторного использования порта в nginx 1.9.1

Что касается вашего основного вопроса, решение проблемы uint16_t исходящего TCP-порты, вероятно, будут заключаться в том, чтобы не использовать серверные части через TCP, когда это вызывает озабоченность и/или использовать дополнительные локальные адреса с помощью директивы proxy_bind и др. (и/или ограничить количество TCP-соединений, которые могут быть установлены с бэкендами).

person cnst    schedule 05.07.2016