Нижча пропускна здатність TCP від ​​1Gbps сервера, ніж 100Mbps сервер на великій 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

Додано декілька зображень графіків вводу-виводу IOS деяких тестових випадків (вибачте, я не можу опублікувати зображення безпосередньо):

Тестовий випадок 1 (100Mbps -> 100Mbps) - приємна плавна передача. Жодних втрат при захопленні. - 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

Отже, підсумовуючи, коли довге посилання використовується підключенням 1Gbps, ми отримуємо набагато нижчу пропускну здатність TCP, ніж коли ми використовуємо 100Mbps-з'єднання.

Я дуже вдячний деяким вказівникам будь-яких експертів TCP там!

Дякую!

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

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

Однак тест №3 здебільшого залишається проблематичним. Якщо у нас приймач працює зі швидкістю 100 Мбіт / с, а відправник - 1 Гбіт / с, то ми бачимо приблизно 2-3 хвилини очікування, коли одержувач досягне 100 Мбіт / с (але він зараз досягає повної швидкості, на відміну від раніше). Як тільки ми опустимо відправника до 100 Мбіт / с або збільшимо приймач до 1 Гбіт / с, тоді проблема зникає, і ми можемо проскочити на повну швидкість через секунду-дві.

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

Пропозиції вдячні, отримані, будь ласка! Якби я міг запропонувати тут щедрості, я би!


1
Чи використовуєте ви завантаження TCP в NIC з обох сторін? Чи ваші витрати на завантаження TCP варіюються від 100M до 1G NIC? Якщо це використовується в будь-якому з тестових випадків, можливо, варто повторити тести з цим відключеним, просто щоб побачити, чи може двигун завантаження TCP в 100M NIC перешкоджає тому, як працює 1G-зв’язок (цей коментар навмисно махнути рукою просто, щоб загалом піднести TOE)
FliesLikeABrick

Хороше питання! Знищення сегментації TCP вимкнено на обох кінцях. Узагальнене завантаження сегментації ввімкнено на обох кінцях. Я також повторив це з включеним TSO, і це не зробило помітних змін.
Сем

Спробуйте відключити загальну сегментацію сегментації, принаймні на стороні 100М, і повторіть свої тести
FliesLikeABrick

Дякую за пропозицію, але ніякої радості - однакові результати із ввімкненням чи вимкненням gso з обох сторін.
Сем

1 Гбіт / с при 150 мс + дає дуже великий продукт із затримкою пропускної здатності, понад 18 Мбіт. Що станеться, якщо ви зіткнете буфери сокетів? tcp_*mem = 4096 1048576 33554432Ви не ввімкнули Jumbo Frames на посилання 1Gbps? Це десь може спричинити фрагментацію.
suprjami

Відповіді:


1

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

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

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

3, ви можете спробувати налаштувати інші параметри tcp, напр. встановити tcp_westwood = 1 і tcp_bic = 1


Дякую, але ми все це спробували. Затримка WAN - це не проблема - ми можемо вражати 100Mbps майже одразу, якщо використовуємо порти 100Mbps, але як тільки один змінюється на 1Gbps, то ми тостимо.
Сем

1

Вирішено! Для отримання детальної інформації див. Http://comments.gmane.org/gmane.linux.drivers.e1000.devel/11813

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

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

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

Сподіваюся, це допоможе комусь у майбутньому.


0

Повторивши ті ж тести над UDP за допомогою iperf, проблема зникає!

Лос-Анджелес (1 Гбіт / с) до Лондона (1 Гбіт / с):> 250 Мбіт / с

Здається, проблеми не зникло, 75% ваших пакетів випадають? Якщо TCP постійно повільно запускається, середня пропускна здатність може бути досить низькою.

Btw, чи є у вас орієнтири для Лондона до Лос-Анджелеса та Лондона до Лондона?


Я забув згадати, що клієнт повільний ... Якщо ми повторимось з двома швидкими клієнтами, то ми б'ємо ~ 970Mbps двосторонньо.
Сем
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.