На максимальное количество соединений влияют определенные ограничения как на стороне клиента, так и на стороне сервера, хотя и немного по-разному.
На стороне клиента:
увеличьте диапазон эфермального порта и уменьшитеtcp_fin_timeout
Чтобы узнать значения по умолчанию:
sysctl net.ipv4.ip_local_port_range
sysctl net.ipv4.tcp_fin_timeout
Диапазон внешних портов определяет максимальное количество исходящих сокетов, которое хост может создать с определенного IP-адреса. 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
было удалено из Linux 4.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-записи . Я предпочитаю использовать буфер, в который я помещаю данные, которые я хочу отправить клиенту, а затем в соответствующих точках записываю буферизованные данные в реальный сокет. Этот метод позволяет мне использовать большие пакеты данных, уменьшить фрагментацию, уменьшить загрузку процессора как на уровне пользователя, так и на уровне ядра.