it-swarm.com.ru

Увеличение максимального количества соединений TCP / IP в Linux

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

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

182
jbu

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

На стороне клиента: Увеличьте диапазон внешних портов и уменьшите 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 ваших сетевых карт также играет определенную роль. Значения по умолчанию - 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 . Я предпочитаю использовать буфер, в который я отправляю данные, которые я хочу отправить клиенту, а затем в соответствующие моменты записываю буферизованные данные в реальный сокет. Этот метод позволяет мне использовать большие пакеты данных, уменьшить фрагментацию, уменьшить загрузку процессора как на уровне пользователя, так и на уровне ядра.

343
mdk

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

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

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

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

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

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

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

57
derobert

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

Вы можете определить, какое ограничение на количество подключений к вашей ОС вы можете, выполнив команду 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}'
15
whitehat237

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

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

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

10
Kev