TCP ouvre-t-il une nouvelle connexion pour chaque paquet envoyé?

15

Cela peut être une question idiote, mais quelques copains et moi avons discuté des limites potentielles de TCP. Nous avons une application qui va écouter les clients (pensez à une passerelle) et acheminer toutes les données des clients connectés via un seul éditeur kafka connecté vers un sujet.

Un de mes amis dit que TCP sera un problème pour cette passerelle car il va établir une nouvelle connexion pour chaque message qu'il envoie (pas kafka mais le protocole de transport sous-jacent lui-même est le problème), nécessitant un nouveau port à chaque fois. Au rythme auquel nous enverrons ces messages clients (gigaoctets), kafka manquera de ports pour lire depuis ??

J'ai fait du développement depuis plusieurs années et je n'en ai jamais entendu parler auparavant et j'aimerais avoir une compréhension de niveau inférieur (que je pensais avoir) du fonctionnement de TCP. Ma compréhension est que lorsque vous établissez une connexion TCP, cette connexion reste ouverte jusqu'à ce qu'elle soit expirée par l'application ou fermée de force par le serveur ou le client. Les données envoyées via cette connexion sont un flux et n'ouvriront / fermeront pas de nouvelles connexions quels que soient les 3 V (volume, vitesse, variété).

En ce qui concerne les ports, un port est utilisé pour la diffusion et le port de descripteur de fichier interne est quelque chose que l'application gère pour la lecture / écriture de clients individuels. Je n'ai jamais compris TCP pour établir de nouvelles connexions pour chaque paquet qu'il écrit.

Je m'excuse à l'avance si cette question n'est pas directe et ou trop vague. Je suis vraiment déconcerté et j'espère que quelqu'un pourrait fournir un peu plus de contexte à ce que disent mes collègues?

user0000001
la source
13
Je pense que vous avez mal compris ce que disait votre ami. TCP ne fait rien de tel, mais il est possible qu'un certain client établisse une nouvelle connexion TCP pour chaque message qu'il souhaite transmettre.
hobbs
13
TCP n'a pas pu ouvrir une nouvelle connexion pour chaque paquet car il a besoin de plusieurs paquets pour ouvrir une nouvelle connexion. Et il n'a pas pu ouvrir une nouvelle connexion pour chaque message car TCP n'a pas de concept de message. Votre copain est très confus. La chose la plus importante à comprendre à propos de TCP, le concept le plus fondamental, est que TCP est un protocole de flux d'octets.
David Schwartz
1
L'argument de votre copain n'est pas nécessairement faux - si vous ne réutilisez pas les ports via la persistance au niveau de l'application ou s'il y a simplement trop de clients, votre système peut manquer de ports éphémères. Il existe des moyens de contourner ce problème: utiliser SO_REUSEADDRpour fermer les sockets plus rapidement, augmenter la plage de ports éphémères, etc. De plus TCP_FASTOPEN, plusieurs bascules au niveau du système d'exploitation peuvent être utilisées pour contourner d'autres limitations bien connues de TCP. Quoi qu'il en soit, il est inutile de discuter des limites de TCP lorsque vous n'avez même pas de charge de travail à tester.
user1643723

Réponses:

22

Un de mes amis dit que TCP sera un problème pour cette passerelle car il va établir une nouvelle connexion pour chaque message qu'il envoie (pas kafka mais le protocole de transport sous-jacent lui-même est le problème), nécessitant un nouveau port à chaque fois. Au rythme auquel nous enverrons ces messages clients (gigaoctets), kafka manquera de ports pour lire depuis ??

Votre ami est très confus. TCP est un protocole orienté flux. Il n'a aucune notion de messages. Bien sûr, il utilise des paquets au niveau de la couche IP, mais pour l'application, c'est un détail d'implémentation. TCP insère les limites des paquets là où il est logique de le faire, et pas nécessairement une fois par write()ousend() . De même, il combine les paquets successifs si vous en recevez plusieurs entre les appels vers read()ou recv().

Il va sans dire que cette conception orientée flux serait totalement irréalisable si chaque envoi établissait une nouvelle connexion. Ainsi, la seule façon d'établir une nouvelle connexion est de fermer et de rouvrir la connexion manuellement.

(En pratique, la plupart des protocoles construits au-dessus de TCP ont quelque chose qui ressemble à des messages, tels que des requêtes et des réponses HTTP. Mais TCP ne connaît pas ou ne se soucie pas de la structure de ces choses.)

Il est possible que votre ami ait pensé à UDP, qui a des messages, mais est également sans connexion. La plupart des implémentations de socket vous permettent de «connecter» un socket UDP à un hôte distant, mais c'est juste un moyen pratique pour éviter d'avoir à spécifier à plusieurs reprises l'adresse IP et le port. Il ne fait rien au niveau du réseau. Néanmoins, vous pouvez suivre manuellement les pairs avec lesquels vous parlez sous UDP. Mais si vous le faites, décider de ce qui compte comme une "connexion" est votre problème, pas celui du système d'exploitation. Si vous souhaitez rétablir une "connexion" sur chaque message, vous pouvez le faire. Ce n'est probablement pas une très bonne idée, cependant.

Kevin
la source
9

Ma compréhension est que lorsque vous établissez une connexion TCP, cette connexion reste ouverte jusqu'à ce qu'elle soit expirée par l'application ou fermée de force par le serveur ou le client.

Du point de vue de TCP, il n'y a ni client ni serveur (client / serveur est un concept d'application hors sujet ici). TCP établit une connexion entre homologues, et les deux homologues peuvent envoyer et recevoir sur la connexion jusqu'à ce que l'un des homologues la ferme ou expire de l'inactivité.

Les données envoyées via cette connexion sont un flux et n'ouvriront / fermeront pas de nouvelles connexions quels que soient les 3 V (volume, vitesse, variété).

Ce qui peut prêter à confusion, c'est que certaines applications, par exemple les navigateurs, ouvriront plusieurs connexions afin de charger simultanément des éléments comme des éléments d'une page Web.

TCP n'ouvre pas une nouvelle connexion pour chaque segment qu'il envoie, mais une application peut ouvrir plusieurs connexions TCP. En outre, lorsqu'une connexion TCP est fermée, le port TCP utilisé dans la connexion est libéré et il est disponible pour être utilisé à nouveau. Cette réponse donne quelques informations et vous indique la RFC pour TCP.

Ron Maupin
la source
2
Bien que dans TCP, il existe un partenaire qui a initié la connexion (souvent appelé "client") et l'autre (souvent appelé "serveur"). Bien sûr, une fois la connexion établie, cette différence n'a plus d'importance.
Paŭlo Ebermann
2
@ PaŭloEbermann, il n'y a rien dans le TCP RFC sur les clients ou les serveurs. Le concept client / serveur est un concept d'application. Ce qui est sur le sujet ici, ce sont les protocoles au niveau ou en dessous de la couche 4 OSI, et il n'y a aucun client ou serveur dans ces protocoles. En fait, ce que vous pouvez supposer être un client (celui qui ouvre une connexion TCP) peut en fait être un serveur d'applications. Nous avons des serveurs qui établissent des connexions TCP aux clients afin d'effectuer des vérifications et des mises à jour de sécurité.
Ron Maupin
7

Non, TCP n'a pas besoin d'ouvrir une nouvelle connexion pour chaque paquet envoyé.

Vous pouvez envoyer plusieurs paquets par le biais de connexions persistantes HTTP , où:

... une seule connexion TCP pour envoyer et recevoir plusieurs requêtes / réponses HTTP [est utilisée], par opposition à l'ouverture d'une nouvelle connexion pour chaque paire requête / réponse unique.

Vous trouverez ci-joint une figure montrant la différence entre plusieurs connexions (plusieurs connexions établies pour envoyer un objet par connexion) et une connexion persistante (une connexion établie et plusieurs objets qui y sont envoyés):

Connexions multiples vs connexion persistante

Source: https://www.vcloudnine.de/how-to-dramately-improve-website-load-times/


la source
7
Cette réponse semble être source de confusion pour les couches. Une requête / réponse HTTP est rarement un seul paquet.
Barmar
2
Sans oublier que chaque "ouverture" est en fait 3 flèches (syn, synack, ack), et chaque "fermeture" est un autre 4 (fin, ack 2x serveur et client), donc s'il y avait effectivement une connexion par paquet, la surcharge s'additionnerait rapidement.
htmlcoderexe
5

Votre interprétation du fonctionnement de TCP est correcte.

Quant à ce que votre ami a dit, je vois deux possibilités ici:

  1. Vous avez mal compris votre ami, qui faisait référence à une limitation de la couche d'application qui se traduit par l'envoi de chaque message via une nouvelle connexion (et ce n'est pas nécessairement inhabituel; il peut ou non être possible de décider de ce comportement, selon le logiciel pile que vous utilisez);

  2. Votre ami a tort.

Courses de légèreté avec Monica
la source
5

Comme d'autres l'ont souligné, TCP permet absolument à une connexion de rester ouverte pendant un certain temps, en échangeant n'importe quel nombre de «messages» dans les deux sens pendant ce temps. Cela dit, il appartient en dernier ressort aux applications (client et serveur) de déterminer si cette capacité est utilisée.

Afin de réutiliser la connexion TCP existante (socket), l'application cliente doit garder cette socket ouverte et l'utiliser lorsqu'elle a besoin d'écrire plus de données. Si le client ne le fait pas, mais jette à la place l'ancien socket et ouvre un nouveau socket à chaque fois qu'il en a besoin, alors il forcera une nouvelle connexion qui pourrait causer des problèmes de ressources sur le client ou le serveur si cela est fait assez fréquemment pour épuiser soit le pool de connexion de la pile TCP.

De même, le serveur doit être suffisamment intelligent pour garder le socket ouvert sur le côté et attendre plus de données. Comme le client, il a la possibilité de fermer le socket, auquel cas un client tolérant aux pannes souhaitant envoyer plus de données n'aura d'autre choix que d'ouvrir un nouveau socket, ce qui entraînera le même problème.

Enfin, comme d'autres l'ont mentionné, TCP est orienté flux. Il n'y a aucun encadrement. Tout simplement parce qu'un homologue a écrit les données d'une manière particulière (par exemple, 1 appel d'écriture de 1 024 octets suivi de 2 256 appels d'écriture d'octets), cela ne garantit pas que l'autre homologue les lira dans les mêmes morceaux (par exemple, il pourrait obtenir tous les 1 536 octets). en un seul appel de lecture). Ainsi, si vous envoyez plusieurs "messages" sur des sockets TCP bruts, vous devez fournir votre propre protocole de trame pour délimiter les différents messages. Bien qu'il existe certainement des moyens simples de le faire, il est généralement peu judicieux car il existe de nombreux protocoles construits sur TCP pour résoudre ce problème. Pour plus de discussion, consultez ceci: https://blog.stephencleary.com/2009/04/message-framing.html

Écossais
la source
2

Je pense que votre ami parlait de HTTP, pas de TCP.

HTTP était à l'origine un protocole sans état: chaque requête HTTP utiliserait une connexion TCP distincte. C'est pourquoi nous avons besoin de cookies (ou quelque chose de similaire) pour implémenter les sessions.

reinierpost
la source
0

Vous avez mentionné "une connexion unique et nécessitant un nouveau port à chaque fois", et j'interpréterais que vous avez de nombreux clients utilisant la technique PAT dans le même environnement réseau pour se connecter au serveur en dehors de votre organisation. Le PAT aurait la limite de 65535 (limite de session TCP sur l'adresse IPv4). Si c'est vrai, vous avez la limite.

TCP ouvre-t-il une nouvelle connexion pour chaque paquet envoyé? NON, cela ne dure pas tant que la session TCP est valide. et ...

Bonjour
la source
0

J'aime l' excellente page wikipedia sur TCP . Il montre clairement ce qui se passe avec le numéro de port. Par chance, il contient également un chapitre utile sur l'utilisation des ressources:

L'utilisation des ressources

La plupart des implémentations allouent une entrée dans une table qui mappe une session à un processus de système d'exploitation en cours d'exécution. Étant donné que les paquets TCP n'incluent pas d'identifiant de session, les deux points de terminaison identifient la session à l'aide de l'adresse et du port du client. Chaque fois qu'un paquet est reçu, l'implémentation TCP doit effectuer une recherche sur cette table pour trouver le processus de destination. Chaque entrée du tableau est connue sous le nom de bloc de contrôle de transmission ou TCB. Il contient des informations sur les points de terminaison (IP et port), l'état de la connexion, l'exécution des données sur les paquets qui sont échangés et les tampons pour l'envoi et la réception de données.

Le nombre de sessions côté serveur n'est limité que par la mémoire et peut augmenter à mesure que de nouvelles connexions arrivent, mais le client doit allouer un port aléatoire avant d'envoyer le premier SYN au serveur. Ce port reste alloué pendant toute la conversation et limite efficacement le nombre de connexions sortantes de chacune des adresses IP du client. Si une application ne parvient pas à fermer correctement les connexions non requises, un client peut manquer de ressources et devenir incapable d'établir de nouvelles connexions TCP, même à partir d'autres applications.

En bref, TCP utilise une ressource très finie, qui est le nombre de ports sur le client (qui est limité par la taille du champ de port dans l'en-tête TCP, 16 bits).

Ainsi, TCP est capable de manquer de ports, si un client ouvre un grand nombre de connexions TCP en parallèle sans les fermer. Le problème se produit uniquement côté client, et il n'importe pas si les connexions sont avec les mêmes adresses IP de serveur ou ports de serveur.

Dans votre environnement, vous semblez avoir une application qui accepte de nombreuses demandes des clients ( cesIl peut s'agir de demandes TCP individuelles, car vos clients l'utilisent peut-être pour consigner certains événements dans votre application et ne maintiennent pas le canal TCP ouvert entre eux), et créer une nouvelle demande interne à votre courtier Kafka (qui pourrait très facilement être des connexions TCP individuelles si vous avez choisi de les implémenter comme ça). Dans ce cas, le goulot d'étranglement (en termes de ressources, pas de performances) serait si vous parvenez à obtenir un grand nombre de demandes en même temps de vos clients (pas de problème pour vous, car côté serveur vous n'avez besoin que d'un port pour tous), et vous ouvrez un grand nombre de demandes de transfert vers votre Kafka, et Kafka n'est pas en mesure de les traiter assez rapidement, vous vous retrouvant avec plus de 16 bits de connexions ouvertes simultanément.

Vous êtes le propre juge ici; vérifiez votre application et essayez de savoir si vous vous connectez à Kafka avec une demande distincte à chaque fois (peut-être via un proxy API REST). Si vous le faites et que vous avez un grand nombre de clients, vous êtes certainement en danger.

Si vous n'avez qu'une poignée de clients, moins de 65k-ish, et / ou vous gardez une seule connexion à votre navigateur Kafka, alors tout ira bien.

AnoE
la source