Wie funktioniert serverseitiges `TIME_WAIT` wirklich?

11

Ich weiß, dass es dazu einige SE-Fragen gibt, und ich glaube, ich habe so viele davon gelesen, wie es wichtig ist, bevor ich zu diesem Punkt komme.

Mit "serverseitig TIME_WAIT" meine ich den Status eines serverseitigen Socket-Paares, dessen close () auf der Serverseite initiiert wurde.

Ich sehe oft diese Aussagen, die mir widersprechen:

  1. Serverseitig TIME_WAITist harmlos
  2. Sie sollten Ihre Netzwerk-Apps so gestalten, dass Clients close () initiieren, damit der Client das trägt TIME_WAIT

Der Grund, warum ich diesen Widerspruch finde, ist, dass TIME_WAITauf dem Client ein Problem auftreten kann - dem Client können die verfügbaren Ports ausgehen. Daher empfiehlt das oben Gesagte im Wesentlichen, die Last TIME_WAITauf die Client-Seite zu verlagern, wo es Probleme geben kann Serverseite, wo es kein Problem ist.

Die Clientseite TIME_WAITist natürlich nur für eine begrenzte Anzahl von Anwendungsfällen ein Problem. Die meisten Client-Server-Lösungen umfassen einen Server und viele Clients. Clients haben normalerweise nicht genügend Verbindungsvolumen, um ein Problem zu verursachen, und selbst wenn dies der Fall ist, gibt es eine Reihe von Empfehlungen, die "vernünftig" sind ( Im Gegensatz zu SO_LINGER0 Timeout oder Einmischung in tcp_tw sysctls) bekämpfen Sie die Clientseite, TIME_WAITindem Sie vermeiden, zu schnell zu viele Verbindungen herzustellen. Dies ist jedoch nicht immer möglich, beispielsweise für Anwendungsklassen wie:

  • Überwachungssysteme
  • Lastgeneratoren
  • Proxies

Auf der anderen Seite verstehe ich nicht einmal, wie TIME_WAIThilfreich die Serverseite überhaupt ist. Der Grund TIME_WAITist sogar da, weil es verhindert, dass abgestandene TCPFragmente in Streams injiziert werden , zu denen sie nicht mehr gehören. Für die Clientseite wird TIME_WAITdies erreicht, indem einfach unmöglich gemacht wird, eine Verbindung mit denselben ip:portPaaren herzustellen, die diese veraltete Verbindung hätte haben können (die verwendeten Paare werden von gesperrt TIME_WAIT). Auf der Serverseite kann dies jedoch nicht verhindert werden, da die lokale Adresse den akzeptierenden Port hat und immer gleich ist und der Server die Verbindung nicht einfach deshalb verweigern kann (AFAIK, ich habe nur den empirischen Beweis) Ein eingehender Peer würde dasselbe Adresspaar erstellen, das bereits in der Socket-Tabelle vorhanden ist.

Ich habe ein Programm geschrieben, das zeigt, dass serverseitiges TIME-WAIT ignoriert wird. Da der Test auf 127.0.0.1 durchgeführt wurde, muss der Kernel außerdem ein spezielles Bit haben, das sogar angibt, ob es sich um eine Server- oder eine Clientseite handelt (da sonst das Tupel dasselbe wäre).

Quelle: http://pastebin.com/5PWjkjEf , getestet auf Fedora 22, Standardnetzkonfiguration.

$ gcc -o rtest rtest.c -lpthread
$ ./rtest 44400 s # will do server-side close
Will initiate server close
... iterates ~20 times successfully
^C
$ ss -a|grep 44400
tcp    TIME-WAIT  0      0            127.0.0.1:44400         127.0.0.1:44401   
$ ./rtest 44500 c # will do client-side close
Will initiate client close
... runs once and then
connecting...
connect: Cannot assign requested address

Auf der Serverseite TIME_WAITkonnten Verbindungen auf genau demselben Portpaar sofort und erfolgreich wiederhergestellt werden, und auf der Clientseite TIME-WAITschlug die zweite Iteration zu connect()Recht fehl

Zusammenfassend ist die Frage zweifach:

  • Tut serverseitig TIME_WAITwirklich nichts und bleibt es einfach so, weil es das RFCerfordert?
  • Ist der Grund der Empfehlung, dass der Client close () initiiert, weil der Server TIME_WAITunbrauchbar ist?
Pawel Veselov
quelle
Sie werden keine Ports mehr haben, es sei denn, Sie haben nur 1 Client. Sie haben 65535 Ports für jede Kombination von Client / Server-IP. Die Verbindung von 1.2.3.4:1111 unterscheidet sich von 4.3.2.1:1111. Es dauert nur wenige Bytes Speicher für jede Verbindung in TIME_WAIT.
Marki555

Antworten:

1

In TCP- Begriffen bedeutet Server-Seite hier den Host, dessen Socket sich im Status LISTEN befindet.

Mit RFC1122 kann der Socket im Status TIME-WAIT unter bestimmten Bedingungen eine neue Verbindung akzeptieren

        When a connection is closed actively, it MUST linger in
        TIME-WAIT state for a time 2xMSL (Maximum Segment Lifetime).
        However, it MAY accept a new SYN from the remote TCP to
        reopen the connection directly from TIME-WAIT state, if it:

Genaue Details zu den Bedingungen finden Sie im RFC1122 . Ich würde erwarten, dass es auch ein passendes passives OPEN am Socket geben muss (Socket im LISTEN-Status).

Active OPEN (clientseitiger Verbindungsaufruf) hat keine solche Ausnahme und muss einen Fehler ausgeben, wenn sich der Socket gemäß RFC793 in TIME-WAIT befindet .

Meine Vermutung für die Empfehlung auf dem Client (in TCP-Begriffen, dass der Host, der aktiv OPEN ausführt, dh eine Verbindung herstellt), der dem Schließen initiiert wurde, entspricht weitgehend Ihrer Empfehlung, dass im allgemeinen Fall die TIME-WAIT-Sockets auf mehr Hosts verteilt werden, für die es eine Fülle von Ressourcen gibt die Steckdosen. Im allgemeinen Fall senden Clients keine SYN, die TIME-WAIT-Sockets auf dem Server wiederverwenden würden. Ich bin damit einverstanden, dass die Anwendung einer solchen Empfehlung immer noch vom Anwendungsfall abhängt.

Marko Kohtala
quelle
0

Dies ist wahrscheinlich das deutlichste Beispiel dafür, was TIME-WAIT tatsächlich tut und was noch wichtiger ist, warum es wichtig ist. Außerdem wird erläutert, warum Sie einige der Expertentipps auf Linux-Computern vermeiden sollten, um die Wartezeiten zu verkürzen.

Khushil
quelle
Erklärt immer noch nicht, was passiert, wenn eine Client-> Server-Verbindung hergestellt wird und ein Server dieses Paar in einem TIME_WAIT
Pawel Veselov
Weitere Informationen finden Sie unter stackoverflow.com/questions/1490196/… - die Antwort dort ist, wonach Sie suchen.
Khushil
0

Eine TCP-Sitzung wird durch das Tupple identifiziert (sourceIP, sourcePort, destIP, destPort). Daher funktioniert TIME_WAIT bei jeder TCP-Verbindung.

In Bezug auf die schließende Seite kann in einigen Szenarien das Schließen von der Client-Seite die TIME_WAIT-Sockets auf dem Server reduzieren, wodurch der Speicher geringfügig reduziert wird. In Fällen, in denen der Socket-Speicherplatz erschöpft sein kann (aufgrund einer kurzlebigen Portverarmung) (z. B. gierige Clients mit vielen Verbindungen zum selben Server), sollte dieses Problem auf jeder Seite gelöst werden.

Basos
quelle
Bitte erkläre; Wenn Sie fragen, ob die serverseitige TW etwas tut, fragen Sie sich, ob dieselbe Verbindung während des TW-Zeitraums wiederverwendet werden kann. Die Antwort lautet Nein, da die vom Tupple definierte Verbindung einen Platz in der TCP-Tabelle des Servers einnimmt. Wenn der Client versucht, dieselbe Verbindung bald zu öffnen, erhält er eine RST, wodurch die TCP-Verbindung effektiv verweigert wird. Der Artikel aus Khushil ist übrigens sehr beschreibend.
Basos
Es tut mir sehr leid, Ihre Antwort beantwortet tatsächlich die Frage, ich habe sie falsch gelesen und meinen Kommentar zurückgezogen. Es scheint jedoch auch falsch zu sein, da ich Code habe, der zu beweisen scheint, dass es keinen Schutz von der Serverseite gibt TIME_WAIT(ich habe die Frage mit diesen Informationen aktualisiert). @ Khushils Referenz behandelt serverseitige TIME_WAITFälle nicht detailliert genug.
Pawel Veselov
-2

Mit einem unzuverlässigen Protokoll können Sie nie sicher sein, dass Sie die letzte Nachricht von Ihrem Peer-Gerät erhalten haben. Daher ist es gefährlich anzunehmen, dass Ihr Peer das Telefon ziemlich plötzlich aufgelegt hat. Es ist ein großer Nachteil des TCP-Protokolls, dass nur etwa 65000 Ports gleichzeitig geöffnet sein können. Der Weg, dies zu überwinden, besteht darin, zu einer Serverfarm zu wechseln, die mit der Last besser skaliert werden kann, als Portnummern schnell zu recyceln. Auf Client-Seite ist es sehr unwahrscheinlich, dass Ihnen die Ports ausgehen, wenn es sich um eine Basisarbeitsstation handelt.

jrrk
quelle
Es tut mir sehr leid, aber das beantwortet meine Frage nicht.
Pawel Veselov