У нас есть инфраструктура, распределенная в нескольких основных местах по всему миру - в Сингапуре, Лондоне и Лос-Анджелесе. 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 Гбит / с, не так ли? Это может быть причиной фрагментации где-то.