Увеличение максимального количества соединений TCP / IP в Linux - PullRequest
182 голосов
/ 04 января 2009

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

Как я могу увеличить или исключить максимальное количество соединений, которое может одновременно открывать мой Ubuntu Linux box? ОС ограничивает это, или это маршрутизатор или провайдер? Или что-то еще?

Ответы [ 4 ]

343 голосов
/ 13 октября 2010

Максимальное количество соединений зависит от определенных ограничений как на стороне клиента, так и на стороне сервера, хотя и немного по-разному.

На стороне клиента: Увеличьте диапазон эфермального порта и уменьшите tcp_fin_timeout

Чтобы узнать значения по умолчанию:

sysctl net.ipv4.ip_local_port_range
sysctl net.ipv4.tcp_fin_timeout

Диапазон внешних портов определяет максимальное количество исходящих сокетов, которое хост может создать из определенного I.P. адрес. fin_timeout определяет минимальное время, в течение которого эти сокеты будут находиться в состоянии TIME_WAIT (невозможно использовать после однократного использования). Обычные системные настройки по умолчанию:

  • net.ipv4.ip_local_port_range = 32768 61000
  • net.ipv4.tcp_fin_timeout = 60

В основном это означает, что ваша система не может постоянно гарантировать более (61000 - 32768) / 60 = 470 сокетов в секунду. Если вас это не устраивает, вы можете начать с увеличения port_range. Установка диапазона на 15000 61000 довольно распространена в наши дни. Вы можете еще больше увеличить доступность, уменьшив fin_timeout. Предположим, что вы делаете оба, вы должны видеть более 1500 исходящих соединений в секунду, с большей готовностью.

Для изменения значений :

sysctl net.ipv4.ip_local_port_range="15000 61000"
sysctl net.ipv4.tcp_fin_timeout=30

Вышесказанное не следует интерпретировать как факторы, влияющие на способность системы выполнять исходящие соединения в секунду. Но скорее эти факторы влияют на способность системы обрабатывать параллельные соединения устойчивым образом в течение больших периодов «активности».

Значения Sysctl по умолчанию в типичной Linux-системе для tcp_tw_recycle & tcp_tw_reuse будут

net.ipv4.tcp_tw_recycle=0
net.ipv4.tcp_tw_reuse=0

Они не разрешают соединение из «используемого» сокета (в состоянии ожидания) и заставляют сокеты длиться полный цикл time_wait. Я рекомендую установить:

sysctl net.ipv4.tcp_tw_recycle=1
sysctl net.ipv4.tcp_tw_reuse=1 

Это позволяет быстро переключать гнезда в состоянии time_wait и повторно использовать их. Но перед тем, как вы сделаете это изменение, убедитесь, что оно не конфликтует с протоколами, которые вы используете для приложения, которому нужны эти сокеты. Обязательно прочитайте пост «Как справиться с TCP-TIME-WAIT» от Винсента Берната , чтобы понять последствия. Параметр net.ipv4.tcp_tw_recycle довольно проблематичен для общедоступных серверов, поскольку он не будет обрабатывать подключения с двух разных компьютеров за одним и тем же устройством NAT , что является проблемой, которую трудно обнаружить и которая ждет вас. Обратите внимание, что net.ipv4.tcp_tw_recycle было удалено из Linux4.12.

На стороне сервера: Значение net.core.somaxconn играет важную роль. Это ограничивает максимальное количество запросов в очереди к сокету прослушивания. Если вы уверены в возможностях вашего серверного приложения, увеличьте его значение по умолчанию со 128 до 128 - 1024. Теперь вы можете воспользоваться этим увеличением, изменив переменную listen backlog в вызове listen вашего приложения на равное или большее целое число.

sysctl net.core.somaxconn=1024

txqueuelen Параметр ваших карт Ethernet также играет роль. Значения по умолчанию - 1000, поэтому увеличьте их до 5000 или даже больше, если ваша система может справиться с этим.

ifconfig eth0 txqueuelen 5000
echo "/sbin/ifconfig eth0 txqueuelen 5000" >> /etc/rc.local

Аналогичным образом увеличьте значения для net.core.netdev_max_backlog и net.ipv4.tcp_max_syn_backlog. Их значения по умолчанию 1000 и 1024 соответственно.

sysctl net.core.netdev_max_backlog=2000
sysctl net.ipv4.tcp_max_syn_backlog=2048

Теперь не забудьте запустить как клиентские, так и серверные приложения, увеличивая значения FD в оболочке.

Помимо вышеупомянутого, еще один популярный метод, используемый программистами, заключается в сокращении количества вызовов tcp write . Я предпочитаю использовать буфер, в который я помещаю данные, которые я хочу отправить клиенту, а затем в соответствующих точках записываю буферизованные данные в реальный сокет. Этот метод позволяет мне использовать большие пакеты данных, уменьшить фрагментацию, уменьшить загрузку процессора как на уровне пользователя, так и на уровне ядра.

57 голосов
/ 04 января 2009

Есть пара переменных для установки максимального количества соединений. Скорее всего, у вас заканчиваются номера файлов в первую очередь. Проверьте ulimit -n. После этого в / proc есть настройки, но они по умолчанию равны десяткам тысяч.

Что еще более важно, похоже, что вы делаете что-то не так. Одно TCP соединение должно иметь возможность использовать всю полосу пропускания между двумя сторонами; если это не так:

  • Проверьте, достаточно ли велика настройка окна TCP. Стандартные настройки Linux хороши для всего, кроме очень быстрой инет-связи (сотни Мбит / с) или быстрой спутниковой связи. Какова ваша пропускная способность * задержка продукта?
  • Проверка потери пакетов с помощью ping с большими пакетами (ping -s 1472 ...)
  • Проверка ограничения скорости. В Linux это настроено с tc
  • Подтвердите, что полоса пропускания, которую вы считаете существующей, действительно существует, например, iperf
  • Подтвердите, что ваш протокол вменяемый. Запомните время ожидания.
  • Если это гигабит + локальная сеть, можете ли вы использовать гигантские пакеты? Вы?

Возможно, я неправильно понял. Может быть, вы делаете что-то вроде Bittorrent, где вам нужно много соединений. Если это так, вам нужно выяснить, сколько соединений вы на самом деле используете (попробуйте netstat или lsof). Если это число является существенным, вы можете:

  • Большая пропускная способность, например, 100 Мбит / с +. В этом случае вам может понадобиться увеличить ulimit -n. Тем не менее, ~ 1000 соединений (по умолчанию в моей системе) довольно мало.
  • Проблемы с сетью, которые замедляют ваши соединения (например, потеря пакетов)
  • Есть что-то еще, что замедляет вас, например, пропускная способность ввода-вывода, особенно если вы ищете. Вы проверили iostat -x?

Кроме того, если вы используете NAT-маршрутизатор потребительского уровня (Linksys, Netgear, DLink и т. Д.), Помните, что вы можете превзойти его возможности с тысячами соединений.

Надеюсь, это поможет. Вы действительно задаете вопрос о сети.

15 голосов
/ 12 октября 2012

Чтобы улучшить ответ Дерберта,

Вы можете определить, какой лимит подключений к вашей ОС вы можете, выбрав nf_conntrack_max.

Например: cat / proc / sys / net / netfilter / nf_conntrack_max

Вы можете использовать следующий скрипт для подсчета количества соединений tcp с заданным диапазоном портов tcp. По умолчанию 1-65535.

Это подтвердит, не превышаете ли вы максимальный лимит подключения к вашей ОС.

Вот сценарий.

#!/bin/bash
OS=$(uname)

case "$OS" in
    'SunOS')
            AWK=/usr/bin/nawk
            ;;
    'Linux')
            AWK=/bin/awk
            ;;
    'AIX')
            AWK=/usr/bin/awk
            ;;
esac

netstat -an | $AWK -v start=1 -v end=65535 ' $NF ~ /TIME_WAIT|ESTABLISHED/ && $4 !~ /127\.0\.0\.1/ {
    if ($1 ~ /\./)
            {sip=$1}
    else {sip=$4}

    if ( sip ~ /:/ )
            {d=2}
    else {d=5}

    split( sip, a, /:|\./ )

    if ( a[d] >= start && a[d] <= end ) {
            ++connections;
            }
    }
    END {print connections}'
10 голосов
/ 20 ноября 2014

На уровне приложения разработчик может сделать следующее:

Со стороны сервера:

  1. Проверьте, правильно ли работает балансировщик нагрузки (если есть).

  2. Превратите медленные тайм-ауты TCP в 503 Быстрое немедленное реагирование. Если вы правильно работаете с балансировщиком нагрузки, он должен выбрать рабочий ресурс для обслуживания, и это лучше, чем зависать там с неожиданными сообщениями об ошибках.

Например: если вы используете сервер узлов, вы можете использовать toobusy из npm. Реализация что-то вроде:

var toobusy = require('toobusy');
app.use(function(req, res, next) {
  if (toobusy()) res.send(503, "I'm busy right now, sorry.");
  else next();
});

Почему 503? Вот некоторые хорошие идеи для перегрузки: http://ferd.ca/queues-don-t-fix-overload.html

Мы можем выполнить некоторую работу и на стороне клиента:

  1. Попробуйте сгруппировать звонки в пакетном режиме, уменьшить трафик и общее количество запросов по ч / б клиенту и серверу.

  2. Попробуйте создать кэш среднего уровня для обработки ненужных дублирующих запросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...