Пропускная способность TCP с сервера 1 Гбит / с по сравнению с сервером 100 Мбит / с по большому RTT

9

У нас есть инфраструктура, распределенная в нескольких основных местах по всему миру - в Сингапуре, Лондоне и Лос-Анджелесе. RTT между любыми двумя точками превышает 150 мс.

Недавно мы обновили все серверы, чтобы использовать ссылки 1 Гбит / с (от 100 Мбит / с). Мы провели несколько тестов на основе TCP между серверами в разных местах и ​​получили некоторые неожиданные результаты. Эти результаты полностью повторяемы.

  1. От Лос-Анджелеса (100 Мбит / с) до Лондона (100 Мбит / с): пропускная способность ~ 96 Мбит / с
  2. От Лос-Анджелеса (100 Мбит / с) до Лондона (1 Гбит / с): пропускная способность ~ 96 Мбит / с
  3. Лос-Анджелес (1 Гбит / с) в Лондон (100 Мбит / с): пропускная способность 10-40 Мбит / с (энергозависимая)
  4. Лос-Анджелес (1 Гбит / с) в Лондон (1 Гбит / с): пропускная способность 10-40 Мбит / с (энергозависимая)
  5. От Лос-Анджелеса (1 Гбит / с) до Лос-Анджелеса (1 Гбит / с): пропускная способность> 900 Мбит / с

Похоже, что всякий раз, когда отправитель работает на скорости 1 Гбит / с, наша пропускная способность очень сильно страдает при длинных каналах.

Предыдущий подход к тестированию чрезвычайно прост - я просто использую cURL для загрузки двоичного файла объемом 1 ГБ с целевого сервера (поэтому в приведенном выше случае клиент cURL работает на сервере в Лондоне и загружает из LA, так что LA является отправителем) , Это использует одно TCP соединение, конечно.

Повторяя те же тесты по UDP, используя iperf, проблема исчезает!

  1. От Лос-Анджелеса (100 Мбит / с) до Лондона (100 Мбит / с): пропускная способность ~ 96 Мбит / с
  2. От Лос-Анджелеса (100 Мбит / с) до Лондона (1 Гбит / с): пропускная способность ~ 96 Мбит / с
  3. Лос-Анджелес (1 Гбит / с) в Лондон (100 Мбит / с): пропускная способность ~ 96 Мбит / с
  4. От Лос-Анджелеса (1 Гбит / с) до Лондона (1 Гбит / с): пропускная способность> 250 Мбит / с

Это прямо указывает на некоторые проблемы конфигурации TCP или NIC / порта в моих глазах.

Оба сервера работают под управлением CentOS 6.x с TCP-кубом. Оба имеют максимальные окна отправки и получения TCP 8 МБ, а также имеют временные метки TCP и выборочные подтверждения. Одна и та же конфигурация TCP используется во всех тестовых случаях. Полная конфигурация TCP ниже:

net.core.somaxconn = 128
net.core.xfrm_aevent_etime = 10
net.core.xfrm_aevent_rseqth = 2
net.core.xfrm_larval_drop = 1
net.core.xfrm_acq_expires = 30
net.core.wmem_max = 8388608
net.core.rmem_max = 8388608
net.core.wmem_default = 131072
net.core.rmem_default = 131072
net.core.dev_weight = 64
net.core.netdev_max_backlog = 1000
net.core.message_cost = 5
net.core.message_burst = 10
net.core.optmem_max = 20480
net.core.rps_sock_flow_entries = 0
net.core.netdev_budget = 300
net.core.warnings = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_retrans_collapse = 1
net.ipv4.tcp_syn_retries = 5
net.ipv4.tcp_synack_retries = 5
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_tw_buckets = 262144
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_retries1 = 3
net.ipv4.tcp_retries2 = 15
net.ipv4.tcp_fin_timeout = 60
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_abort_on_overflow = 0
net.ipv4.tcp_stdurg = 0
net.ipv4.tcp_rfc1337 = 0
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_orphan_retries = 0
net.ipv4.tcp_fack = 1
net.ipv4.tcp_reordering = 3
net.ipv4.tcp_ecn = 2
net.ipv4.tcp_dsack = 1
net.ipv4.tcp_mem = 1528512      2038016 3057024
net.ipv4.tcp_wmem = 4096        131072  8388608
net.ipv4.tcp_rmem = 4096        131072  8388608
net.ipv4.tcp_app_win = 31
net.ipv4.tcp_adv_win_scale = 2
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_frto = 2
net.ipv4.tcp_frto_response = 0
net.ipv4.tcp_low_latency = 0
net.ipv4.tcp_no_metrics_save = 0
net.ipv4.tcp_moderate_rcvbuf = 1
net.ipv4.tcp_tso_win_divisor = 3
net.ipv4.tcp_congestion_control = cubic
net.ipv4.tcp_abc = 0
net.ipv4.tcp_mtu_probing = 0
net.ipv4.tcp_base_mss = 512
net.ipv4.tcp_workaround_signed_windows = 0
net.ipv4.tcp_dma_copybreak = 4096
net.ipv4.tcp_slow_start_after_idle = 1
net.ipv4.tcp_available_congestion_control = cubic reno
net.ipv4.tcp_allowed_congestion_control = cubic reno
net.ipv4.tcp_max_ssthresh = 0
net.ipv4.tcp_thin_linear_timeouts = 0
net.ipv4.tcp_thin_dupack = 0

Приложены несколько изображений графиков ввода-вывода wireshark некоторых тестовых случаев (извините, я пока не могу публиковать изображения напрямую):

Тестовый пример 1 (100 Мбит / с -> 100 Мбит / с) - хорошая плавная передача. Никаких потерь в захвате. - http://103.imagebam.com/download/dyNftIGh-1iCFbjfMFvBQw/25498/254976014/100m.png

Тестовый пример 3 (1 Гбит / с -> 100 Мбит / с) - голосовая передача, для достижения любой скорости требуется много времени - никогда не приближается к 100 Мбит / с. Пока нет потерь / ретрансляций в захвате! - http://101.imagebam.com/download/KMYXHrLmN6l0Z4KbUYEZnA/25498/254976007/1g.png

Итак, в итоге, когда длинное соединение используется с соединением 1 Гбит / с, мы получаем намного меньшую пропускную способность TCP, чем когда мы используем соединение 100 Мбит / с.

Я был бы очень признателен за советы от всех экспертов по TCP!

Спасибо!

ОБНОВЛЕНИЕ (2013-05-29):

Мы решили проблему с помощью контрольного примера № 4 (отправитель 1 Гбит / с, приемник 1 Гбит / с, через большой RTT). Теперь мы можем набрать ~ 970 Мбит / с в течение нескольких секунд после начала передачи. Похоже, проблема связана с хостинг-провайдером. Переход к другому решил это.

Тем не менее, тестовый пример № 3 в основном остается проблематичным. Если у нас есть приемник, работающий на скорости 100 Мбит / с, а отправитель на скорости 1 Гбит / с, то мы видим примерно 2-3 минуты ожидания, пока приемник достигнет 100 Мбит / с (но теперь он достигает полной скорости, в отличие от ранее). Как только мы опускаем отправителя до 100 Мбит / с или увеличиваем приемник до 1 Гбит / с, проблема исчезает, и мы можем разогнаться до полной скорости в секунду или две.

Основная причина в том, что мы видим потери, конечно же, очень скоро после начала перевода. Однако это не соответствует моему пониманию того, как работает медленный запуск; скорость интерфейса не должна иметь к этому никакого отношения, так как она должна регулироваться ACK от приемника.

Предложения с благодарностью получены, пожалуйста! Если бы я мог предложить щедрость здесь, я бы!

Сэм
источник
1
Используете ли вы TCP разгрузки на сетевой карте с обеих сторон? Изменяется ли использование TCP разгрузки от 100M до 1G NIC? Если это используется в каком-либо из тестовых случаев, возможно, стоит повторить тесты с отключенным, просто чтобы посмотреть, может ли механизм разгрузки TCP на 100M NIC мешать выполнению связи 1G (этот комментарий намеренно махнул рукой, чтобы вообще воспитать TOE)
FliesLikeABrick
Хороший вопрос! Разгрузка сегментации TCP отключена на обоих концах. Общая разгрузка сегментации включена на обоих концах. Я также повторил это с включенным TSO, и это не имело никакого заметного различия.
Сэм
Попробуйте отключить общую разгрузку сегментации, по крайней мере, на стороне 100M, и повторите свои тесты
FliesLikeABrick
Спасибо за предложение, но не радость - одинаковые результаты при включенном или выключенном gso с обеих сторон.
Сэм
1 Гбит / с при 150 мс + дает очень большой продукт с задержкой полосы пропускания, более 18 Мб. Что произойдет, если вы увеличите буферы сокетов? tcp_*mem = 4096 1048576 33554432Вы не включили Jumbo Frames в ссылках 1 Гбит / с, не так ли? Это может быть причиной фрагментации где-то.
suprjami

Ответы:

1

Основная проблема - большая задержка глобальной сети. Будет еще хуже, если он также потеряет случайный пакет.

1, tcp_mem также нужно установить большим, чтобы выделить больше памяти. Например, установите его как net.ipv4.tcp_mem = 4643328 6191104 9286656

2, вы можете захватывать пакеты через wireshark / tcpdump в течение нескольких минут, а затем анализировать, была ли потеряна случайная передача. Вы также можете загрузить файл пакетов, если хотите.

3, вы можете попытаться настроить другие параметры TCP, например. установить tcp_westwood = 1 и tcp_bic = 1

HarryREN
источник
Спасибо, но мы попробовали все это. Задержка глобальной сети не является проблемой - мы можем набрать 100 Мбит / с почти сразу, если будем использовать порты 100 Мбит / с, но как только мы изменим на 1 Гбит / с, мы будем тостом.
Сэм
1

Решено! Для получения полной информации см. Http://comments.gmane.org/gmane.linux.drivers.e1000.devel/11813

Короче говоря, похоже, что подключенный сервер со скоростью 1 Гбит / с будет отправлять пакеты трафика во время фазы экспоненциального роста TCP, что приведет к переполнению буферов в каком-либо промежуточном устройстве (кто знает, что). Это оставляет два варианта:

1) Свяжитесь с каждым оператором промежуточной сети и попросите их настроить соответствующие буферы для обеспечения желаемой пропускной способности и RTT. Довольно маловероятно! 2) Ограничить всплески.

Я решил ограничить каждый поток TCP максимально 100 Мбит / с. Число здесь довольно произвольно - я выбрал 100 Мбит / с исключительно потому, что знал, что предыдущий путь может обрабатывать 100 Мбит / с, и мне больше не нужны отдельные потоки .

Надеюсь, это поможет кому-то в будущем.

Сэм
источник
0

Повторяя те же тесты по UDP, используя iperf, проблема исчезает!

От Лос-Анджелеса (1 Гбит / с) до Лондона (1 Гбит / с): пропускная способность> 250 Мбит / с

Проблема, похоже, не исчезла, примерно 75% ваших пакетов теряются? Если TCP все время медленно запускается, средняя полоса пропускания может быть довольно низкой.

Кстати, у вас есть ориентиры для Лондона в Лос-Анджелесе и Лондона в Лондон?

Йенс Тиммерман
источник
Я забыл упомянуть, что клиент медленный ... Если мы повторим с двумя быстрыми клиентами, то мы получим ~ 970 Мбит / с в двух направлениях.
Сэм