Я использую ядро Linux 3.13 (Ubuntu 14.04) на двух виртуальных машинах, каждая из которых работает на двух разных серверах под управлением ESXi 5.1. Между двумя виртуальными машинами запущено клиент-серверное приложение zeromq. После запуска в течение 10-30 минут это приложение постоянно зависает из-за невозможности повторно передать потерянный пакет.
Когда я запускаю ту же настройку через Ubuntu 12.04 (Linux 3.11), приложение никогда не завершается с ошибкой (ОБНОВЛЕНИЕ: также происходит сбой 12.04, но занимает больше времени)
Если вы заметили ниже, " сс "(статистика сокетов) показывает 1 потерянный пакет, sk_wmem_queued = 14110 (т. е. w14110) и высокое значение rto (120000).
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 **12350** 192.168.2.122:41808 192.168.2.172:55550
timer:(on,16sec,10) uid:1000 ino:35042
sk:ffff880035bcb100 <->
skmem:(r0,rb648720,t0,tb1164800,f2274,**w14110**,o0,bl0) ts sack cubic wscale:7,7 rto:120000 rtt:7.5/3 ato:40 mss:8948 cwnd:1 ssthresh:21 send 9.5Mbps **unacked:1 retrans:1/10 lost:1** rcv_rtt:1476 rcv_space:37621
Так как это происходило так последовательно, я смог перехватить протокол TCP в wireshark. Я обнаружил, что потерянный пакет действительно повторно передается и даже подтверждается TCP в другой ОС (порядковый номер виден в ACK), но отправитель, похоже, не понимает этот ACK и продолжает повторную передачу.
MTU составляет 9000 на обеих виртуальных машинах и через весь маршрут. Отправляемые пакеты имеют большой размер.
Как я уже говорил ранее, этого не происходит в Ubuntu 12.04 (ядро 3.11). Поэтому я провел различие по параметрам конфигурации TCP (через sysctl -a | grep tcp) между 14.04 и 12.04 и обнаружил следующие различия.
Я также заметил, что net.ipv4.tcp_mtu_probing = 0 в обеих конфигурациях.
Левая сторона 3,11, правая сторона 3,13
<<net.ipv4.tcp_abc = 0
<<net.ipv4.tcp_cookie_size = 0
<<net.ipv4.tcp_dma_copybreak = 4096
14c11
<< net.ipv4.tcp_early_retrans = 2
---
>> net.ipv4.tcp_early_retrans = 3
17c14
<< net.ipv4.tcp_fastopen = 0
>> net.ipv4.tcp_fastopen = 1
20d16
<< net.ipv4.tcp_frto_response = 0
26,27c22
<< net.ipv4.tcp_max_orphans = 16384
<< net.ipv4.tcp_max_ssthresh = 0
>> net.ipv4.tcp_max_orphans = 4096
29,30c24,25
<< net.ipv4.tcp_max_tw_buckets = 16384
<< net.ipv4.tcp_mem = 94377 125837 188754
>> net.ipv4.tcp_max_tw_buckets = 4096
>> net.ipv4.tcp_mem = 23352 31138 46704
34a30
>> net.ipv4.tcp_notsent_lowat = -1
Мой вопрос к сетевым экспертам на этом форуме: есть ли какие-либо другие средства отладки или опции, которые я могу установить / включить, чтобы узнать, почему это Ошибка повторной передачи TCP происходит так последовательно? Есть ли какие-либо изменения конфигурации, которые могут объяснить это странное поведение?
ОБНОВЛЕНИЕ (для тех, кто может столкнуться с подобной проблемой позже): я смог воспроизвести проблему и на 3.11, а затем смог обойти эту проблему, снизив MTU.
О подобной проблеме сообщалось здесь https://serverfault.com/questions/488893/how-do-i-prevent-tcp-connection-freezes-over-an-openvpn-network . Приведенное там описание совпадает с тем, что я видел:
«В какой-то момент с клиентами Ubuntu удаленный конец начинает повторную передачу одного и того же сегмента TCP снова и снова (с увеличением задержки передачи между каждой повторной передачей» Клиент отправляет то, что выглядит как действительный TCP ACK, для каждой повторной передачи, но удаленный конец все еще периодически передает один и тот же сегмент TCP. "
Возможно, связанная статья: https: / /blogs.kent.ac.uk/unseenit/2013/10/18/stalled-scp-and-hanging-tcp-connections/
Он мы заметили ту же проблему: ядро Linux 3.2 на Ubuntu 12.04 работало без любых проблем, Linux 3.13 на Ubuntu 14.02 имел ту же проблему.
я не уверен, является ли это действительно ошибкой в ядре, мне оно больше походит на проблему с выборочным ACKs (SACK). Вы можете обходное решение проблема путем отключения TCP SACK с:
sysctl net.ipv4.tcp_sack=0
Это работало вокруг проблемы. В нашем случае это происходило, что клиенты с или далекими соединениями с потерями (например, различные дата-центры, абонентские линии DSL) больше не были не смочь загрузить большие файлы. Приблизительно после нескольких мегабайтов, загружающих остановленное HTTP-соединение. TCDump показал много выборочных ACKS переданные (МЕШКИ).
И да, загружая 12,04 ядер в 14,04 помог, также.
я думаю, что мы должны открыть проблему в Ubuntu. Я был просто не уверен, происходит ли проблема только из-за нашей сети/оборудования маршрутизатора, но обычно проблеме кажется, что TCP SACK является неправильным.