Baut TCP für jedes gesendete Paket eine neue Verbindung auf?


15

Dies mag eine dumme Frage sein, aber ein Ich und einige Freunde haben die möglichen Einschränkungen von TCP diskutiert. Wir haben eine Anwendung, die auf Clients wartet (denken Sie an ein Gateway) und alle verbundenen Client-Daten über einen einzigen verbundenen Kafka-Publisher zu einem Thema weiterleitet.

Einer meiner Freunde sagt, dass TCP ein Problem für dieses Gateway sein wird, da es für jede gesendete Nachricht eine neue Verbindung herstellen wird (nicht Kafka, sondern das zugrunde liegende Transportprotokoll selbst ist das Problem) und jedes Mal einen neuen Port benötigt. Bei der Geschwindigkeit, mit der wir diesen Clients Nachrichten (Gigabyte) senden, gehen kafka die Ports aus, von denen gelesen werden kann ??

Ich habe mehrere Jahre lang an der Entwicklung gearbeitet und noch nie davon gehört. Ich würde gerne ein tieferes Verständnis (von dem ich dachte, ich hätte es) für die Funktionsweise von TCP erlangen. Wenn Sie eine TCP-Verbindung herstellen, bleibt diese nach meinem Verständnis geöffnet, bis die Zeitüberschreitung durch die Anwendung abgelaufen ist oder der Server oder der Client die Verbindung zwangsweise geschlossen hat. Daten, die über diese Verbindung gesendet werden, sind ein Stream und öffnen / schließen keine neuen Verbindungen, unabhängig von den 3 V (Lautstärke, Geschwindigkeit, Sorte).

In Bezug auf die Ports wird ein Port für die Übertragung verwendet, und der interne Dateideskriptor-Port wird von der Anwendung zum Lesen / Schreiben einzelner Clients verwaltet. Ich habe nie verstanden, dass TCP für jedes Paket, das es schreibt, neue Verbindungen herstellt.

Ich entschuldige mich im Voraus, wenn diese Frage nicht direkt und / oder zu vage ist. Ich bin wirklich verblüfft und hoffe, dass jemand mehr Kontext zu den Aussagen meiner Kollegen liefern kann?


13
Ich glaube, Sie haben falsch verstanden, was Ihr Freund gesagt hat. TCP macht so etwas nicht, aber es ist möglich, dass ein bestimmter Client für jede Nachricht, die er weiterleiten möchte , eine neue TCP-Verbindung herstellt .
Hobbs

13
TCP konnte möglicherweise keine neue Verbindung für jedes Paket herstellen, da zum Herstellen einer neuen Verbindung mehrere Pakete erforderlich sind. Und es konnte keine neue Verbindung für jede Nachricht hergestellt werden, da TCP kein Konzept für eine Nachricht hat. Dein Kumpel ist sehr verwirrt. Das wichtigste Verständnis von TCP, dem grundlegendsten Konzept, ist, dass TCP ein Byte-Stream-Protokoll ist.
David Schwartz

1
Die Argumentation Ihres Freundes ist nicht unbedingt falsch - wenn Sie Ports nicht über Keep-Alive auf Anwendungsebene wiederverwenden oder einfach zu viele Clients vorhanden sind, werden Ihrem System möglicherweise die kurzlebigen Ports ausgehen. Es gibt Möglichkeiten, um dieses Problem SO_REUSEADDRzu umgehen : Verwenden Sie , um Sockets schneller zu schließen, die Reichweite von ephemeren Ports usw. zu erhöhen. Darüber hinaus können TCP_FASTOPENmehrere Umschalter auf Betriebssystemebene verwendet werden, um andere bekannte Einschränkungen von TCP zu umgehen. In beiden Fällen macht es keinen Sinn, die Einschränkungen von TCP zu diskutieren, wenn Sie nicht einmal eine Workload zum Testen haben.
user1643723

Antworten:


22

Einer meiner Freunde sagt, dass TCP ein Problem für dieses Gateway sein wird, da es für jede gesendete Nachricht eine neue Verbindung herstellen wird (nicht Kafka, sondern das zugrunde liegende Transportprotokoll selbst ist das Problem) und jedes Mal einen neuen Port benötigt. Bei der Geschwindigkeit, mit der wir diesen Clients Nachrichten (Gigabyte) senden, gehen kafka die Ports aus, von denen gelesen werden kann ??

Dein Freund ist sehr verwirrt. TCP ist ein streamorientiertes Protokoll. Es hat keine Ahnung von Nachrichten. Natürlich werden Pakete auf der IP-Ebene verwendet, aber für die Anwendung ist dies ein Implementierungsdetail. TCP fügt Paketgrenzen ein, wo dies sinnvoll ist, und nicht unbedingt einmal pro write()odersend() . In ähnlicher Weise werden aufeinanderfolgende Pakete miteinander kombiniert, wenn Sie zwischen Anrufen an read()oder mehr als ein Paket erhalten recv().

Es erübrigt sich zu erwähnen, dass dieses Stream-orientierte Design völlig unbrauchbar wäre, wenn jeder Send eine neue Verbindung herstellen würde. Die einzige Möglichkeit, eine neue Verbindung herzustellen, besteht darin, die Verbindung manuell zu schließen und erneut zu öffnen.

(In der Praxis haben die meisten Protokolle, die auf TCP aufbauen, etwas, das Nachrichten ähnelt, z. B. HTTP-Anforderungen und -Antworten. TCP kennt die Strukturen solcher Dinge jedoch nicht oder kümmert sich nicht darum.)

Möglicherweise hat Ihr Freund an UDP gedacht, das zwar Nachrichten enthält, aber auch verbindungslos ist. Bei den meisten Socket-Implementierungen können Sie ein UDP-Socket mit einem Remotehost "verbinden". Dies ist jedoch nur eine bequeme Möglichkeit, um zu vermeiden, dass die IP-Adresse und der Port wiederholt angegeben werden müssen. Auf Netzwerkebene wird eigentlich nichts ausgeführt. Sie können jedoch manuell nachverfolgen, mit welchen Peers Sie unter UDP sprechen. Aber wenn Sie das tun, ist es Ihr Problem, zu entscheiden, was als "Verbindung" zählt, nicht das des Betriebssystems. Wenn Sie bei jeder Nachricht eine "Verbindung" wiederherstellen möchten, können Sie dies tun. Es ist jedoch wahrscheinlich keine sehr gute Idee.


9

Wenn Sie eine TCP-Verbindung herstellen, bleibt diese nach meinem Verständnis geöffnet, bis die Zeitüberschreitung durch die Anwendung abgelaufen ist oder der Server oder der Client die Verbindung zwangsweise geschlossen hat.

Aus Sicht von TCP gibt es keinen Client oder Server (Client / Server ist ein Anwendungskonzept, das hier nicht zum Thema gehört). TCP stellt eine Verbindung zwischen Peers her, und beide Peers können über die Verbindung senden und empfangen, bis sie von einem Peer geschlossen wird oder eine Zeitüberschreitung aufgrund von Inaktivität auftritt.

Daten, die über diese Verbindung gesendet werden, sind ein Stream und öffnen / schließen keine neuen Verbindungen, unabhängig von den 3 V (Lautstärke, Geschwindigkeit, Sorte).

Was verwirrend sein kann, ist, dass einige Anwendungen, z. B. Browser, mehrere Verbindungen öffnen, um gleichzeitig Elemente einer Webseite zu laden.

TCP öffnet keine neue Verbindung für jedes Segment, das es sendet, aber eine Anwendung kann mehrere TCP-Verbindungen öffnen. Wenn eine TCP-Verbindung geschlossen wird, wird der in der Verbindung verwendete TCP-Port freigegeben und kann wieder verwendet werden. Diese Antwort enthält einige Informationen und verweist auf den RFC für TCP.


2
In TCP gibt es jedoch einen Partner, der die Verbindung initiiert hat (häufig als "Client" bezeichnet), und einen anderen Partner (häufig als "Server" bezeichnet). Nachdem die Verbindung hergestellt wurde, spielt dieser Unterschied natürlich keine Rolle mehr.
Paŭlo Ebermann

2
@ PaŭloEbermann, im TCP-RFC gibt es nichts über Clients oder Server. Das Client / Server-Konzept ist ein Anwendungskonzept. Hier geht es um Protokolle auf oder unter OSI-Ebene 4, und diese Protokolle enthalten keine Clients oder Server. Tatsächlich kann es sich bei dem, was Sie als Client (derjenige, der eine TCP-Verbindung herstellt) annehmen, um einen Anwendungsserver handeln. Wir haben Server, die TCP-Verbindungen zu Clients initiieren, um beispielsweise Sicherheitsüberprüfungen und Updates durchzuführen.
Ron Maupin

7

Nein, TCP muss nicht für jedes gesendete Paket eine neue Verbindung herstellen.

Sie können mehrere Pakete über dauerhafte HTTP-Verbindungen senden , wobei:

... eine einzelne TCP-Verbindung zum Senden und Empfangen mehrerer HTTP-Anforderungen / Antworten [wird verwendet], anstatt für jedes einzelne Anforderungs- / Antwortpaar eine neue Verbindung herzustellen.

Angefügt ist eine Abbildung, die den Unterschied zwischen mehreren Verbindungen (viele Verbindungen wurden hergestellt, um ein Objekt pro Verbindung zu senden) und einer dauerhaften Verbindung (eine Verbindung wurde hergestellt und mehrere Objekte wurden darin gesendet) zeigt:

Mehrere Verbindungen im Vergleich zu dauerhaften Verbindungen

Quelle: https://www.vcloudnine.de/how-to-dramatically-improve-website-load-times/


7
Diese Antwort scheint verwirrend zu sein. Eine HTTP-Anfrage / Antwort ist selten ein einzelnes Paket.
Barmar

2
Ganz zu schweigen davon, dass jedes "Öffnen" tatsächlich 3 Pfeile (syn, synack, ack) und jedes "Schließen" weitere 4 Pfeile (fin, ack 2x Server und Client) enthält. Wenn also tatsächlich eine Verbindung pro Paket besteht, entsteht der Overhead würde schnell summieren.
htmlcoderexe

5

Ihre Interpretation der Funktionsweise von TCP ist korrekt.

Was Ihre Freundin gesagt hat, sehe ich hier zwei Möglichkeiten:

  1. Sie haben Ihren Freund missverstanden, der auf eine Einschränkung der Anwendungsebene verwiesen hat, die dazu führt, dass jede Nachricht über eine neue Verbindung gesendet wird (und dies ist nicht unbedingt ungewöhnlich; je nach Software kann dieses Verhalten möglicherweise festgelegt werden Stapel, den Sie verwenden);

  2. Dein Freund ist falsch.


5

Wie bereits erwähnt, lässt TCP zu, dass eine Verbindung für einen beliebigen Zeitraum geöffnet bleibt und in diesem Zeitraum beliebig viele "Nachrichten" in beide Richtungen ausgetauscht werden. Letztendlich liegt es jedoch an den Anwendungen (sowohl Client als auch Server), zu bestimmen, ob diese Fähigkeit genutzt wird.

Um die vorhandene TCP-Verbindung (Socket) wiederzuverwenden, muss die Clientanwendung diesen Socket geöffnet lassen und verwenden, wenn weitere Daten geschrieben werden müssen. Wenn der Client dies nicht tut, sondern stattdessen den alten Socket verwirft und jedes Mal einen neuen Socket öffnet, erzwingt er in der Tat eine neue Verbindung, die Ressourcenprobleme auf dem Client oder dem Server verursachen kann, wenn sie häufig genug ausgeführt werden, um die Ressourcen zu erschöpfen entweder der Verbindungspool des TCP-Stacks.

Ebenso muss der Server intelligent genug sein, um den Socket offen zu halten und auf weitere Daten zu warten. Wie der Client hat er die Möglichkeit, den Socket zu schließen. An diesem Punkt hat ein fehlertoleranter Client, der mehr Daten senden möchte, keine andere Wahl, als einen neuen Socket zu öffnen, was zu demselben Problem führt.

Schließlich ist TCP, wie andere bereits erwähnt haben, stream-orientiert. Es gibt überhaupt keine Rahmung. Nur weil ein Peer die Daten auf eine bestimmte Art und Weise geschrieben hat (z. B. 1 1024-Byte-Schreibaufruf gefolgt von 2 256-Byte-Schreibaufrufen), kann dies nicht garantieren, dass der andere Peer sie in Blöcken gleicher Größe liest (z. B. alle 1536 Byte abrufen kann in einem Leseaufruf). Wenn Sie also mehrere "Nachrichten" über unformatierte TCP-Sockets senden, müssen Sie Ihr eigenes Framing-Protokoll angeben, um die verschiedenen Nachrichten abzugrenzen. Es gibt zwar einfache Möglichkeiten, dies zu tun, es ist jedoch im Allgemeinen nicht ratsam, da viele Protokolle auf TCP aufbauen, um dieses Problem zu lösen. Weitere Informationen finden Sie unter https://blog.stephencleary.com/2009/04/message-framing.html


2

Ich glaube, dein Freund hat über HTTP gesprochen, nicht über TCP.

HTTP war ursprünglich ein zustandsloses Protokoll: Für jede HTTP-Anforderung wurde eine separate TCP-Verbindung verwendet. Aus diesem Grund benötigen wir Cookies (oder ähnliches), um Sitzungen zu implementieren.


0

Sie haben "Einzelverbindung und erfordern jedes Mal einen neuen Port" erwähnt, und ich würde interpretieren, dass Sie viele Clients haben, die die PAT-Technik in derselben Netzwerkumgebung verwenden, um eine Verbindung zu einem Server außerhalb Ihrer Organisation herzustellen. Die PAT hat das Limit von 65535 (TCP-Sitzungslimit für IPv4-Adresse). Wenn es wahr ist, haben Sie das Limit.

Baut TCP für jedes gesendete Paket eine neue Verbindung auf? NEIN, solange die TCP-Sitzung gültig ist. und ...


0

Ich mag die ausgezeichnete Wikipedia-Seite über TCP . Es wird deutlich, was mit der Portnummer passiert. Zufällig enthält es auch ein hilfreiches Kapitel zur Ressourcennutzung:

Ressourcennutzung

Die meisten Implementierungen weisen einen Eintrag in einer Tabelle zu, die eine Sitzung einem ausgeführten Betriebssystemprozess zuordnet. Da TCP-Pakete keine Sitzungskennung enthalten, identifizieren beide Endpunkte die Sitzung anhand der Adresse und des Ports des Clients. Immer wenn ein Paket empfangen wird, muss die TCP-Implementierung eine Suche in dieser Tabelle durchführen, um den Zielprozess zu finden. Jeder Eintrag in der Tabelle wird als Transmission Control Block oder TCB bezeichnet. Es enthält Informationen über die Endpunkte (IP und Port), den Status der Verbindung, laufende Daten zu den auszutauschenden Paketen und Puffer zum Senden und Empfangen von Daten.

Die Anzahl der Sitzungen auf der Serverseite ist nur durch den Arbeitsspeicher begrenzt und kann mit dem Eintreffen neuer Verbindungen zunehmen. Der Client muss jedoch einen zufälligen Port zuweisen, bevor er die erste SYN an den Server sendet. Dieser Port bleibt während der gesamten Konversation zugewiesen und begrenzt effektiv die Anzahl der ausgehenden Verbindungen von jeder IP-Adresse des Clients. Wenn eine Anwendung nicht die erforderlichen Verbindungen ordnungsgemäß schließt, können einem Client die Ressourcen ausgehen und er kann keine neuen TCP-Verbindungen mehr herstellen, auch nicht von anderen Anwendungen aus.

Kurz gesagt, TCP belegt eine sehr begrenzte Ressource, dh die Anzahl der Ports auf dem Client (die durch die Größe des Portfelds im TCP-Header (16 Bit) begrenzt ist).

Also, TCP ist die Lage der Häfen auslaufen zu lassen, wenn ein Client eine Menge von TCP - Verbindungen parallel eröffnet , ohne sie zu schließen. Das Problem tritt nur clientseitig auf, und es spielt keine Rolle, ob die Verbindungen mit denselben oder unterschiedlichen Server-IP-Adressen oder Server-Ports bestehen.

In Ihrer Einstellung haben Sie anscheinend eine Anwendung, die viele Clientanforderungen ( diese) verarbeitetDies können einzelne TCP-Anforderungen sein, da Ihre Clients dies möglicherweise verwenden, um einige Ereignisse in Ihrer Anwendung zu protokollieren und den TCP-Kanal nicht dazwischen offen zu halten. Außerdem können Sie eine neue interne Anforderung an Ihren Kafka-Broker erstellen (bei der es sich sehr leicht um einzelne TCP-Verbindungen handeln kann wenn Sie sie so implementieren möchten). In diesem Fall besteht der Engpass (in Bezug auf Ressourcen, nicht Leistung) darin, dass Sie eine große Anzahl von Anfragen gleichzeitig von Ihren Clients erhalten (für Sie kein Problem, da Sie auf der Serverseite nur einen Port benötigen) alle von ihnen), und Sie eröffnen Ihrem Kafka eine große Anzahl von Weiterleitungsanforderungen, und Kafka kann sie nicht schnell genug verarbeiten, was dazu führt, dass Verbindungen mit mehr als 16 Bit gleichzeitig geöffnet sind.

Sie sind der eigene Richter hier; Überprüfen Sie Ihre Anwendung und versuchen Sie herauszufinden, ob Sie mit einer separaten Anfrage eine Verbindung zu Kafka herstellen (möglicherweise über einen REST-API-Proxy). Wenn Sie dies tun und eine große Anzahl von Kunden haben, sind Sie mit Sicherheit in Gefahr.

Wenn Sie nur eine Handvoll Clients haben, die kleiner als 65.000 sind, und / oder eine einzige Verbindung zu Ihrem Kafka-Browser haben, ist alles in Ordnung.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.