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