Увеличение максимального количества подключений tcp/ip в Linux

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

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

Ответ 1

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

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

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

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

Диапазон ephermal port определяет максимальное количество исходящих сокетов, которые хост может создать из определенного 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 и повторно использовать их. Но прежде чем вы сделаете это изменение, убедитесь, что это не противоречит протоколам, которые вы будете использовать для приложения, которое нуждается в этих сокетах.

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

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 ulimts в оболочке.

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

Ответ 2

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

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

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

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

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

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

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

Ответ 3

Чтобы улучшить ответ, данный derobert,

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

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

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

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

Здесь script.

#!/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}'

Ответ 4

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

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

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

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

Например: если вы используете сервер node, вы можете использовать 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

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

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

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