Ich habe Verzögerungen beim Senden von Daten über einen TCP-Kanal, den ich nicht verstehen kann. Die Verbindung ist eine 1-GB-Verbindung mit einer End-to-End-Latenz von ungefähr 40 ms. In meinem aktuellen Setup kann die Latenz (die Zeit von einer Nachricht vom Senderbenutzerbereich zum Empfängerbenutzerbereich) 100 ms erreichen.
Der Absendersocket wird mit der Option TCP_NODELAY konfiguriert. Der Senderpuffer (SO_SNDBUF) ist auf 8 MB konfiguriert. Der Empfangspuffer (SO_RCVBUF) ist ebenfalls auf 8 MB konfiguriert. Die TCP-Fensterskalierung ist aktiviert.
Update-1 : Ich verwende die Zeromq 3.1.1 Middleware, um Daten zu übertragen. Die Socket-Konfiguration einschließlich des TCP_NODELAY-Flags wird von der Middleware durchgeführt. Auf einige Optionen kann zugegriffen werden, z. B. rx und tx senden Puffergrößen aus, nicht jedoch TCP_NODELAY. Soweit ich verstanden habe, wird TCP_NODELAY aktiviert, um sicherzustellen, dass die Daten so gut wie möglich gesendet werden. In der Zwischenzeit werden die tatsächlichen Socket-Sendungen und die Entscheidung zum Senden einer Nachricht in zwei separaten Threads ausgeführt. Eine ordnungsgemäße Stapelverarbeitung erfolgt, wenn zum Zeitpunkt des Versendens der ersten Nachricht im Stapel mehrere Nachrichten verfügbar sind.
Ich habe mit tcpdump ein Capture ausgeführt, aus dem die folgenden Frames extrahiert wurden. Nach dem ersten TCP-Handshake beginnt der Absender (172.17.152.124) mit dem Senden von Daten. Die anfängliche Fenstergröße beträgt 5840 Byte für den Empfänger und 5792 Byte für den Absender.
Mein Problem ist, dass der Absender zwei Frames sendet (Nr. 6 und Nr. 7) und dann anhält und darauf wartet, dass eine Bestätigung vom Empfänger zurückkommt. Soweit ich sehen kann, wird die Fenstergröße des Empfängers nicht erreicht und die Übertragung sollte nicht gestoppt werden (384 Bytes ausstehend bei einer anfänglichen Empfangsfenstergröße von 5840 Bytes). Ich fange an zu denken, dass ich nicht richtig verstanden habe, was TCP ist. Kann jemand bei der Klärung helfen?
Update-2 : Meine Datennutzlast besteht aus einer magischen Zahl, gefolgt von einem Zeitstempel. Ich habe die verzögerten Pakete isoliert, indem ich die Zeitstempel der Nutzdaten mit den von tcpdump gesetzten Zeitstempeln verglichen habe. Die Nutzlast ts von Frame # 9 liegt sehr nahe an der von Frame # 6 und # 7 und deutlich unter dem Zeitstempel der empfangenen Bestätigung in Frame # 8.
Update-1 : Die Tatsache, dass Frame # 9 nicht sofort gesendet wird, kann durch den langsamen Start des TCP-Kanals erklärt werden. Tatsächlich tritt das Problem auch auf, wenn die Verbindung einige Minuten lang ausgeführt wird, sodass der langsame Start nicht die allgemeine Erklärung zu sein scheint.
20: 53: 26.017415 IP 172.17.60.9.39943> 172.17.152.124.56001: Flags [S], seq 2473022771, win 5840, options [mss 1460, sackOK, TS val 4219180820 ecr 0, nop, wscale 8], Länge 0
20: 53: 26.017423 IP 172.17.152.124.56001> 172.17.60.9.39943: Flags [S.], seq 2948065596, ack 2473022772, win 5792, options [mss 1460, sackOK, TS val 186598852 ecr 219180820, nop, wscale 9 ], Länge 0
20: 53: 26.091940 IP 172.17.60.9.39943> 172.17.152.124.56001: Flags [.], Ack 1, Win 23, Optionen [nop, nop, TS val 4219180894 ecr 186598852], Länge 0
20: 53: 26.091958 IP 172.17.60.9.39943> 172.17.152.124.56001: Flags [P.], Seq. 1:15, ack 1, w in 23, Optionen [nop, nop, TS val 4219180895 ecr 186598852], Länge 14
20: 53: 26.091964 IP 172.17.152.124.56001> 172.17.60.9.39943: Flags [.], Ack 15, Win 12, Optionen [nop, nop, TS val 186598927 ecr 4219180895], Länge 0
20: 53: 26.128298 IP 172.17.152.124.56001> 172.17.60.9.39943: Flags [P.], Sequenz 1: 257, ack 15, win 12, Optionen [nop, nop, TS val 186598963 ecr 4219180895], Länge 256
20: 53: 26.128519 IP 172.17.152.124.56001> 172.17.60.9.39943: Flags [P.], Sequenz 257: 385, ack 15, win 12, Optionen [nop, nop, TS val 186598963 ecr 4219180895], Länge 128
20: 53: 26.202465 IP 172.17.60.9.39943> 172.17.152.124.56001: Flags [.], Ack 257, Win 27, Optionen [nop, nop, TS val 4219181005 ecr 186598963], Länge 0
20: 53: 26.202475 IP 172.17.152.124.56001> 172.17.60.9.39943: Flags [.], Seq 385: 1833, ack 15, win 12, options [nop, nop, TS val 186599037 ecr 4219181005], Länge 1448
20: 53: 26.202480 IP 172.17.152.124.56001> 172.17.60.9.39943: Flags [P.], seq 1833: 2305, ack 15, win 12, options [nop, nop, TS val 186599037 ecr 4219181005], Länge 472
In diesem Fall handelt es sich bei beiden Enden um Linux-RHEL5-Boxen, wobei 2.6.18-Kernel und Netzwerkkarten e1000e-Treiber verwenden.
update-3 Inhalt von /etc/sysctl.conf
[jlafaye@localhost ~]$ cat /etc/sysctl.conf | grep -v "^#" | grep -v "^$"
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 1048576
net.core.wmem_default = 1048576
net.ipv4.tcp_rmem = 65536 4194304 16777216
net.ipv4.tcp_wmem = 65536 4194304 16777216
net.core.netdev_max_backlog = 10000
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_mem = 262144 4194304 16777216
kernel.shmmax = 68719476736
/etc/sysctl.conf
?