Назад | Перейти на главную страницу

Плохая пропускная способность для одиночных TCP-соединений

У меня есть сервер с гигабитным восходящим каналом, и я тестирую его с 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 и ваш сервер поддерживают его.