2012-03-07 2 views
3

Я разрабатываю код, который имитирует сетевое оборудование. Мне нужно запустить несколько тысяч симулированных «агентов», и каждый из них должен подключиться к службе. Проблема в том, что после открытия 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-адресов.

+0

Это не ulimit. Это дало бы «слишком много ошибок открытых файлов». Я получаю таймауты соединения (с гнездом в SYN_SENT). Мой ulimit составляет 50 000. – Hisnessness

+0

В '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'означает, –

+0

Используете ли вы 'select()' (в этом случае переключитесь на 'poll()')? – ninjalj

ответ

2

Что такое DOH-момент. Я смотрел сервер, используя netstat, и так как я не видел большого количества подключений, я не думал, что есть проблема. Но в конце концов я поумнел и проверил /var/log/kernel, в котором я нашел это:

Mar 8 11:03:52 TestServer01 kernel: ipv4: Neighbour table overflow. 

Это привело меня к этой публикации: http://www.serveradminblog.com/2011/02/neighbour-table-overflow-sysctl-conf-tunning/, который объясняет, как увеличить лимит. Нажатие значения thresh3 сразу же решило проблему.

0

Возможно, вы захотите посмотреть настройки sysctl, связанные с net.ipv4.

Эти настройки включают в себя такие вещи, как maxconntrack и другие соответствующие настройки, которые вы, возможно, захотите настроить.

+0

Я посмотрел, но я не могу найти ничего, что кажется применимым. – Hisnessness

0

Вы абсолютно уверены, что проблема не связана с подключением на стороне сервера, не закрывая сокеты? то есть, что показывает lsof -n -p серверного процесса? Что показывает процесс plimit -p сервера? Серверная сторона может быть привязана к тому, что она не сможет принимать больше соединений, а клиентская сторона получает результат EINPROGRESS.

Проверьте ulimit на количество открытых файлов с обеих сторон соединения - 1024 слишком близко к уровню ulimit, чтобы быть совпадением.

+0

Я наблюдал за netstat -t -n на сервере, и я не вижу никакого влияния. – Hisnessness