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

Иногда невозможно настроить стек TCP Linux для повышения производительности с высокой задержкой

Я безуспешно пытался применить методы настройки TCP, обсуждаемые на http://fasterdata.es.net/host-tuning/

Как вы увидите, когда прочитаете весь вопрос, иногда рекомендации по настройке es.net эффективны для меня, а иногда нет, и я еще не могу понять, каковы отличительные факторы.

У меня настроена эталонная лабораторная среда со следующим:

Эти две машины соединены через высокоскоростную внутреннюю сеть с высокой пропускной способностью, которую я использую в тестовых целях.

Моими основными инструментами для анализа на данный момент были iperf, pchar, tcpdump и Wireshark.

Для начала я запускаю iperf -s на моем Mac и iperf -c на моем компьютере Linux, и я надежно и воспроизводимо получаю измеренную пропускную способность примерно 940 Мбит / с, что имеет смысл для меня, потому что я считаю, что мои машины подключен через сеть 1 Гбит / с.

Я подтверждаю эти измерения с помощью «pchar».

Затем я искусственно ввожу в это соединение высокую задержку, выполняя следующие действия:

tc qdisc add dev eth0 root netem delay 78ms

Как только я это сделаю, iperf и pchar сообщают, что полоса пропускания резко падает до диапазона 75–100 Мбит / с.

Интересно, что цифры также сильно колеблются. Но они одинаково ужасны.

Я считаю, что это соответствует описанной здесь проблеме: http://fasterdata.es.net/host-tuning/background/ и поэтому я хочу заметить, что я могу (отчасти) решить эту проблему, настроив стеки TCP на двух машинах.

На Mac я использую sysctl -w, чтобы установить

net.inet.tcp.win_scale_factor=8
kern.ipc.maxsockbuf=4194304
net.inet.tcp.recvspace=2097152

Попытка установить для kern.ipc.maxsockbuf более высокое значение отклонена операционной системой как «слишком большой результат». Это может быть ограничением данной версии Mac OS X, как описано здесь: https://discussions.apple.com/thread/2581395 (Я еще не пробовал сложный обход этого ограничения, описанный здесь: https://www.myricom.com/software/myri10ge/391-how-can-i-restore-the-socket-buffer-sizes-in-macosx-10-6.html)

Между тем, на машине с Linux я использую sysctl -w для установки

net.core.wmem_max=16777216
net.ipv4.tcp_wmem = 4096 8388608 16777216
net.core.rmem_max=16777216
net.ipv4.tcp_rmem = 4096 8388608 16777216

Однако ни одна из этих настроек, похоже, не меняет цифры, сообщаемые iperf.

После того, как все настройки вступили в силу, iperf по-прежнему сообщает измеренную пропускную способность около 90 Мбит / с, насколько я могу судить без изменений из значений до того, как я внес изменения в настройку.

Я захватил следы пакетов этой конфигурации с помощью tcpdump и просмотрел их с помощью Wireshark, и насколько я могу судить, сообщения ACK, поступающие с Mac обратно на машину Linux, указывают размер окна почти 4 МБ.

Тем не менее, следы пакетов, по-видимому, говорят мне, что машина с Linux не желает отправлять более 32 КБ неподтвержденных данных за один раз, и «бегущие байты» никогда не превышают этого значения.

Трассировка пакетов не показывает никаких доказательств потери пакетов, таких как сообщения повторной передачи; тем не менее, они иногда показывают некоторые свидетельства переупорядочения пакетов.

Что я делаю не так? Почему методы настройки TCP описаны на http://fasterdata.es.net/host-tuning/ у меня не работает?

ОБНОВИТЬ:

Я использовал tcptrace -lW для трассировки пакета tcpdump одного из таких запусков, и результаты показаны ниже.

TCP connection 3:
    host e:        *****:55706
    host f:        *****:5001
    complete conn: yes
    first packet:  Tue Sep  8 07:48:35.569180 2015
    last packet:   Tue Sep  8 07:48:55.823746 2015
    elapsed time:  0:00:20.254566
    total packets: 112524
    filename:      sample.pcap
   e->f:                  f->e:
     total packets:         91306           total packets:         21218      
     ack pkts sent:         91305           ack pkts sent:         21218      
     pure acks sent:            2           pure acks sent:        21216      
     sack pkts sent:            0           sack pkts sent:          820      
     dsack pkts sent:           0           dsack pkts sent:           0      
     max sack blks/ack:         0           max sack blks/ack:         3      
     unique bytes sent: 131989528           unique bytes sent:         0      
     actual data pkts:      91303           actual data pkts:          0      
     actual data bytes: 132057584           actual data bytes:         0      
     rexmt data pkts:          47           rexmt data pkts:           0      
     rexmt data bytes:      68056           rexmt data bytes:          0      
     zwnd probe pkts:           0           zwnd probe pkts:           0      
     zwnd probe bytes:          0           zwnd probe bytes:          0      
     outoforder pkts:           0           outoforder pkts:           0      
     pushed data pkts:        435           pushed data pkts:          0      
     SYN/FIN pkts sent:       1/1           SYN/FIN pkts sent:       1/1      
     req 1323 ws/ts:          Y/Y           req 1323 ws/ts:          Y/Y      
     adv wind scale:            9           adv wind scale:            6      
     req sack:                  Y           req sack:                  Y      
     sacks sent:                0           sacks sent:              820      
     urgent data pkts:          0 pkts      urgent data pkts:          0 pkts 
     urgent data bytes:         0 bytes     urgent data bytes:         0 bytes
     mss requested:          1460 bytes     mss requested:          1460 bytes
     max segm size:          1448 bytes     max segm size:             0 bytes
     min segm size:            24 bytes     min segm size:             0 bytes
     avg segm size:          1446 bytes     avg segm size:             0 bytes
     max win adv:           29696 bytes     max win adv:         3728256 bytes
     min win adv:           29696 bytes     min win adv:         3116992 bytes
     zero win adv:              0 times     zero win adv:              0 times
     avg win adv:           29696 bytes     avg win adv:         3725120 bytes
     max owin:             695209 bytes     max owin:                  1 bytes
     min non-zero owin:         1 bytes     min non-zero owin:         1 bytes
     avg owin:             129597 bytes     avg owin:                  1 bytes
     wavg owin:            186185 bytes     wavg owin:                 0 bytes
     initial window:        13056 bytes     initial window:            0 bytes
     initial window:           10 pkts      initial window:            0 pkts 
     ttl stream length: 131989528 bytes     ttl stream length:         0 bytes
     missed data:               0 bytes     missed data:               0 bytes
     truncated data:            0 bytes     truncated data:            0 bytes
     truncated packets:         0 pkts      truncated packets:         0 pkts 
     data xmit time:       20.095 secs      data xmit time:        0.000 secs 
     idletime max:           81.0 ms        idletime max:           79.8 ms   

Я не понимаю, почему средний овин остается таким маленьким.

Я чувствую, что это связано с окном перегрузки, но я не понимаю, почему окно перегрузки ограничивает мою пропускную способность.

Я использовал инструмент Linux ss, чтобы наблюдать за cwnd во время моего прогона, и он действительно показывает мне, что cwnd не увеличивается:

State      Recv-Q Send-Q      Local Address:Port          Peer Address:Port   
ESTAB      0      696600        N.N.N.N:55708         N.N.N.N:5001    
     skmem:(r0,rb8388608,t482,tb2097152,f3584,w2097664,o0,bl0) cubic wscale:8,9 rto:280 rtt:80/3 mss:1448 cwnd:486 ssthresh:328 send 70.4Mbps unacked:482 retrans:0/89 rcv_space:29200
...

    ESTAB      0      626984        N.N.N.N:55708         N.N.N.N:5001    
     skmem:(r0,rb8388608,t243,tb2097152,f216832,w1884416,o0,bl0) cubic wscale:8,9 rto:280 rtt:80/3 mss:1448 cwnd:243 ssthresh:240 send 35.2Mbps unacked:243 retrans:0/231 rcv_space:29200
...
ESTAB      0      697936        N.N.N.N:55708         N.N.N.N:5001    
     skmem:(r0,rb8388608,t289,tb2097152,f3584,w2097664,o0,bl0) cubic wscale:8,9 rto:276 rtt:79.5/3 mss:1448 cwnd:290 ssthresh:240 send 42.3Mbps unacked:290 retrans:0/231 rcv_space:29200

Есть ли в этом выводе ss какие-нибудь подсказки относительно того, почему у меня такая низкая пропускная способность?

ОБНОВЛЕНИЕ 2

Я получил доступ к дополнительным аппаратным ресурсам.

В частности, мне удалось найти альтернативный Linux-сервер и использовать его для тестирования на моем Mac. Еще раз, в Linux я смоделировал соединение с высокой задержкой, выполнив:

tc qdisc add dev eth0 root netem delay 78ms

В этом ящике я снова выполнил инструкции из http://fasterdata.es.net/host-tuning/ установить переменные

net.core.wmem_max=16777216
net.ipv4.tcp_wmem = 4096 8388608 16777216
net.core.rmem_max=16777216
net.ipv4.tcp_rmem = 4096 8388608 16777216

Затем iperf сообщил об измеренной пропускной способности между двумя машинами, равной 911 мегабит в секунду.

Итак, теперь я успешно применил методы настройки TCP на компьютере с Linux.

НО, я по-прежнему озадачен, почему те же самые методы не работали на другом компьютере с Linux.

Во второй настройке есть как минимум два важных отличия:

  1. В моем неудачном эксперименте машина Linux была виртуальной машиной, а в моем успешном эксперименте машина Linux работала на голом железе.
  2. В моем неудачном эксперименте виртуальная машина Linux и мой Mac находились в разных подсетях, разделенных маршрутизатором, в то время как в моем успешном эксперименте машина Linux и мой Mac находились в одной подсети.

Итак, возможно, методы, перечисленные в http://fasterdata.es.net/host-tuning/ не работают, если настраиваемая машина Linux является виртуальной машиной, возможно, потому, что сетевой стек Linux в виртуальной машине существенно отличается от сетевого стека Linux на машине Linux с голым железом и, следовательно, не реагирует на ту же настройку.

Или, возможно, методы, перечисленные в http://fasterdata.es.net/host-tuning/ не работают, если между конечными точками стоит маршрутизатор (хотя, поскольку вся точка http://fasterdata.es.net/host-tuning/ предназначен для настройки WAN в масштабе Интернета, безусловно, должно быть почти ВСЕГДА я бы подумал, что это маршрутизатор между конечными точками?).

Или, возможно, есть какой-то другой фактор, который различается между моими двумя экспериментами, что является причиной ужасающей производительности в первом случае (но что это может быть?)