Я разрабатываю код, который имитирует сетевое оборудование. Мне нужно запустить несколько тысяч симулированных «агентов», и каждый из них должен подключиться к службе. Проблема в том, что после открытия 1023 соединений, соединения начинают отсчет времени, и все это рушится.Не удается открыть более 1023 розетки
Основной код находится в Go, но я написал очень тривиальный скрипт python, который воспроизводит проблему.
Единственное, что несколько необычно, это то, что мы должны установить локальный адрес в сокете при его создании. Это связано с тем, что оборудование, к которому подключаются агенты, ожидает, что кажущийся IP будет соответствовать тому, что мы говорим. Для этого я настроил 10 000 виртуальных интерфейсов (eth0: 1 до eth0: 10000). Им назначаются уникальные IP-адреса в частной сети.
Питон скрипт только это (работает только до 2000 connnects):
import socket
i = 0
for b in range(10, 30):
for d in range(1, 100):
i += 1
ip = "1.%d.1.%d" % (b, d)
print("Conn %i %s" % (i, ip))
s = socket.create_connection(("1.6.1.1", 5060), 10, (ip, 5060))
Если удалить последний аргумент socket.create_connection (адрес источника), то я могу получить все 2000 подключений.
Дело в том, что отличается с использованием локального адреса является то, что привязка должна быть сделана до того, как соединение может быть установлено, так что выход из этой программы, работающей под Трассирование выглядит следующим образом:
Conn 1023 1.20.1.33
bind(3, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(5060), sin_addr=inet_addr("1.20.1.33")}, 16) = 0
connect(3, {sa_family=AF_INET, sin_port=htons(5060), sin_addr=inet_addr("1.6.1.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
If Я бегу без локального адреса, привязка AF_INET уходит, и он работает.
Итак, кажется, что существует определенное ограничение на количество связок, которые могут быть сделаны. Я пропустил всевозможные ссылки о настройке TCP в Linux, и я попытался возиться с tcp_tw_reuse/recycle, и я сократил fin_timeout, и я сделал другие вещи, которые я не могу вспомнить.
Это работает на Ubuntu Linux (11.04, ядро 2.6.38 (64 бит). Это виртуальная машина на кластере VMWare ESX.
Просто, прежде чем отправлять это, я попытался запустить вторые экземпляры питона скрипт с дополнительным запуском в 1.30.1.1. Первый скрипт распахивал до 1023 соединений, но второй не смог даже выполнить первый, указав, что проблема связана с большим количеством виртуальных интерфейсов. внутренняя структура данных будет ограничена? Некоторая максимальная установка памяти где-то?
Может ли кто-нибудь подумать о каком-то ограничении в Linux, который может вызвать это?
Обновление:
Сегодня утром я решил попробовать эксперимент. Я модифицировал скрипт python для использования «основного» интерфейса IP в качестве исходного IP-адреса и эфемерных портов в диапазоне 10000+. Сценарий теперь выглядит следующим образом:
import socket
i = 0
for i in range(1, 2000):
print("Conn %i" % i)
s = socket.create_connection(("1.6.1.1", 5060), 10, ("1.1.1.30", i + 10000))
Этот скрипт работает просто отлично, так что это добавляет к моему убеждению, что проблема связана с большим количеством псевдонимов IP-адресов.
Это не ulimit. Это дало бы «слишком много ошибок открытых файлов». Я получаю таймауты соединения (с гнездом в SYN_SENT). Мой ulimit составляет 50 000. – Hisnessness
В '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'означает, –
Используете ли вы 'select()' (в этом случае переключитесь на 'poll()')? – ninjalj