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