У нас есть инфраструктура, распределенная в нескольких основных местах по всему миру - в Сингапуре, Лондоне и Лос-Анджелесе. RTT между любыми двумя точками превышает 150 мс.
Недавно мы обновили все серверы, чтобы использовать ссылки 1 Гбит / с (от 100 Мбит / с). Мы провели несколько тестов на основе TCP между серверами в разных местах и получили некоторые неожиданные результаты. Эти результаты полностью повторяемы.
- От Лос-Анджелеса (100 Мбит / с) до Лондона (100 Мбит / с): пропускная способность ~ 96 Мбит / с
- От Лос-Анджелеса (100 Мбит / с) до Лондона (1 Гбит / с): пропускная способность ~ 96 Мбит / с
- Лос-Анджелес (1 Гбит / с) в Лондон (100 Мбит / с): пропускная способность 10-40 Мбит / с (энергозависимая)
- Лос-Анджелес (1 Гбит / с) в Лондон (1 Гбит / с): пропускная способность 10-40 Мбит / с (энергозависимая)
- От Лос-Анджелеса (1 Гбит / с) до Лос-Анджелеса (1 Гбит / с): пропускная способность> 900 Мбит / с
Похоже, что всякий раз, когда отправитель работает на скорости 1 Гбит / с, наша пропускная способность очень сильно страдает при длинных каналах.
Предыдущий подход к тестированию чрезвычайно прост - я просто использую cURL для загрузки двоичного файла объемом 1 ГБ с целевого сервера (поэтому в приведенном выше случае клиент cURL работает на сервере в Лондоне и загружает из LA, так что LA является отправителем) , Это использует одно TCP соединение, конечно.
Повторяя те же тесты по UDP, используя iperf, проблема исчезает!
- От Лос-Анджелеса (100 Мбит / с) до Лондона (100 Мбит / с): пропускная способность ~ 96 Мбит / с
- От Лос-Анджелеса (100 Мбит / с) до Лондона (1 Гбит / с): пропускная способность ~ 96 Мбит / с
- Лос-Анджелес (1 Гбит / с) в Лондон (100 Мбит / с): пропускная способность ~ 96 Мбит / с
- От Лос-Анджелеса (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 от приемника.
Предложения с благодарностью получены, пожалуйста! Если бы я мог предложить щедрость здесь, я бы!
источник
tcp_*mem = 4096 1048576 33554432
Вы не включили Jumbo Frames в ссылках 1 Гбит / с, не так ли? Это может быть причиной фрагментации где-то.Ответы:
Основная проблема - большая задержка глобальной сети. Будет еще хуже, если он также потеряет случайный пакет.
1, tcp_mem также нужно установить большим, чтобы выделить больше памяти. Например, установите его как net.ipv4.tcp_mem = 4643328 6191104 9286656
2, вы можете захватывать пакеты через wireshark / tcpdump в течение нескольких минут, а затем анализировать, была ли потеряна случайная передача. Вы также можете загрузить файл пакетов, если хотите.
3, вы можете попытаться настроить другие параметры TCP, например. установить tcp_westwood = 1 и tcp_bic = 1
источник
Решено! Для получения полной информации см. Http://comments.gmane.org/gmane.linux.drivers.e1000.devel/11813
Короче говоря, похоже, что подключенный сервер со скоростью 1 Гбит / с будет отправлять пакеты трафика во время фазы экспоненциального роста TCP, что приведет к переполнению буферов в каком-либо промежуточном устройстве (кто знает, что). Это оставляет два варианта:
1) Свяжитесь с каждым оператором промежуточной сети и попросите их настроить соответствующие буферы для обеспечения желаемой пропускной способности и RTT. Довольно маловероятно! 2) Ограничить всплески.
Я решил ограничить каждый поток TCP максимально 100 Мбит / с. Число здесь довольно произвольно - я выбрал 100 Мбит / с исключительно потому, что знал, что предыдущий путь может обрабатывать 100 Мбит / с, и мне больше не нужны отдельные потоки .
Надеюсь, это поможет кому-то в будущем.
источник
Проблема, похоже, не исчезла, примерно 75% ваших пакетов теряются? Если TCP все время медленно запускается, средняя полоса пропускания может быть довольно низкой.
Кстати, у вас есть ориентиры для Лондона в Лос-Анджелесе и Лондона в Лондон?
источник