NGINX: Превышено ограничение в 65535 соединений

В отличие от HTTP, websocket сохраняет долгоживущее соединение после его обновления с HTTP.

Даже если ОС настроена на использование всех портов, в общей сложности всего 65536 портов. Возможно ли, чтобы NGINX превысил это ограничение?

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

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

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

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

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

1 ответ

Решение

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

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, сколько позволяет его память. - Кукурузные початки 4 декабря 15 в 2:36

Однако при оценке того, будете ли вы выходить за пределы ограничений, вы также должны учитывать, что 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 вернуть строку "ОК" вместо файла. Я сравнил три конфигурации NGINX: стандартная (эквивалентная для accept_mutex), с выключенным accept_mutex и с повторным портом. Как показано на рисунке, повторный порт увеличивает количество запросов в секунду в 2–3 раза и уменьшает как задержку, так и стандартное отклонение для задержки.

Сравнительный реэкспорт в nginx 1.9.1

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

Другие вопросы по тегам