У меня есть сервер с гигабитным восходящим каналом, и я тестирую его с iperf3
со 100 параллельными соединениями я получаю не менее 600 Мбит / с, в зависимости от другого сервера (я пробовал несколько общедоступных тестовых серверов). Но когда я бегу iperf3
с одним подключением я получаю 10-15 MBit/s
, с двумя 20-30 MBit/s
и так далее.
У меня нет очень сложных правил iptables и других идей, почему это так медленно. Что может быть ограничивающим фактором для одиночных TCP-соединений, если они в 10 раз медленнее, чем возможная пропускная способность?
Я наконец нашел причину проблемы.
У меня было какое-то веб-приложение flask, которое использует redis для потоковой передачи событий пользователю. Когда пользователь отключился, приложение поддерживало соединение redis pubsub, больше не считывая данные.
Это приводит к долгому Send-Q
/Recv-Q
, что, по-видимому, приводит к замедлению работы стека TCP и выдаче предупреждений ядра: "TCP: недостаточно памяти - рассмотрите возможность настройки tcp_mem".
Одиночные сеансы TCP ограничены размером окна каждого сеанса, которое представляет максимальное количество байтов, которые могут быть «в движении» между двумя конечными точками в любой момент времени. Поэтому, если у вас высокая задержка на вашем канале, вы можете достичь ограничения на сеанс, равного windowSize / RTT.
Единственный способ обойти это (поскольку вы обычно не можете многое сделать с RTT) - либо использовать больше сеансов, либо значительно увеличить размер окна с помощью масштабирования окна. Я не знаю, какие настройки iPerf относятся к этому, и может ли у вас быть брандмауэр или другой фильтр между конечными точками, который предотвращает масштабирование, даже если iPerf и ваш сервер поддерживают его.