TCP apre una nuova connessione per ogni pacchetto inviato?


15

Questa potrebbe essere una domanda sciocca, ma io e pochi amici abbiamo discusso dei potenziali limiti di TCP. Abbiamo un'applicazione che ascolterà i client (pensa a un gateway) e instraderà tutti i dati dei client connessi attraverso un singolo editore kafka connesso a un argomento.

Uno dei miei amici sta dicendo che TCP sarà un problema per questo gateway perché stabilirà una nuova connessione per ogni messaggio che invia (non kafka ma lo stesso protocollo di trasporto sottostante è il problema), che richiede una nuova porta ogni volta. Alla velocità in cui invieremo questi messaggi client (gigabyte), kafka esaurirà le porte da cui leggere ??

Ho fatto lo sviluppo per diversi anni e non ne ho mai sentito parlare prima e vorrei avere una comprensione di livello inferiore (che pensavo di avere) su come funziona TCP. La mia comprensione è che quando si stabilisce una connessione TCP, tale connessione rimane aperta fino a quando non viene scaduta dall'applicazione o chiusa forzatamente dal server o dal client. I dati inviati tramite questa connessione sono uno stream e non apriranno / chiuderanno nuove connessioni indipendentemente dai 3 V (volume, velocità, varietà).

Per quanto riguarda le porte, una porta viene utilizzata per la trasmissione e la porta del descrittore di file interno è qualcosa che l'applicazione gestisce per la lettura / scrittura dei singoli client. Non ho mai capito che TCP stabilisse nuove connessioni per ogni pacchetto che scrive.

Mi scuso in anticipo se questa domanda non è diretta e o troppo vaga. Sono davvero sconcertato e spero che qualcuno possa fornire un po 'più di contesto a ciò che dicono i miei colleghi?


13
Penso che tu abbia frainteso quello che stava dicendo il tuo amico. TCP non fa nulla del genere, ma è possibile che un determinato client stabilisca una nuova connessione TCP per ogni messaggio che desidera passare.
Hobbs

13
TCP non è stato in grado di aprire una nuova connessione per ogni pacchetto perché ha bisogno di diversi pacchetti per aprire una nuova connessione. E non è stato possibile aprire una nuova connessione per ogni messaggio perché TCP non ha il concetto di un messaggio. Il tuo amico è molto confuso. La cosa più importante da capire su TCP, il concetto più fondamentale, è che TCP è un protocollo a flusso di byte.
David Schwartz,

1
L'argomento del tuo amico non è necessariamente sbagliato: se non riutilizzi le porte tramite keep-alive a livello di applicazione o ci sono semplicemente troppi client, il tuo sistema potrebbe rimanere senza porte effimere. Esistono modi per ovviare a questo problema: utilizzare SO_REUSEADDRper chiudere più rapidamente socket, aumentare la gamma di porte effimere ecc. Inoltre, è TCP_FASTOPENpossibile utilizzare diversi interruttori a livello di sistema operativo per aggirare altre limitazioni ben note di TCP. In ogni caso, non ha senso discutere le limitazioni di TCP quando non si ha nemmeno un carico di lavoro su cui testare.
user1643723

Risposte:


22

Uno dei miei amici sta dicendo che TCP sarà un problema per questo gateway perché stabilirà una nuova connessione per ogni messaggio che invia (non kafka ma lo stesso protocollo di trasporto sottostante è il problema), che richiede una nuova porta ogni volta. Alla velocità in cui invieremo questi messaggi client (gigabyte), kafka esaurirà le porte da cui leggere ??

Il tuo amico è gravemente confuso. TCP è un protocollo orientato al flusso. Non ha nozione di messaggi. Ovviamente, utilizza i pacchetti a livello IP, ma per l'applicazione si tratta di un dettaglio di implementazione. TCP inserisce i confini dei pacchetti dove ha senso farlo, e non necessariamente una volta per write()osend() . Allo stesso modo, combina insieme i pacchetti successivi se ne ricevi più di uno tra le chiamate a read()o recv().

Inutile dire che questo design orientato al flusso sarebbe completamente inattuabile se ogni invio stabilisse una nuova connessione. Pertanto, l'unico modo per stabilire una nuova connessione è chiudere e riaprire la connessione manualmente.

(In pratica, la maggior parte dei protocolli costruiti su TCP hanno qualcosa che ricorda i messaggi, come richieste e risposte HTTP. Ma TCP non conosce o si preoccupa delle strutture di tali cose.)

È possibile che il tuo amico stesse pensando a UDP, che ha messaggi, ma è anche privo di connessione. La maggior parte delle implementazioni di socket consente di "connettere" un socket UDP a un host remoto, ma questo è solo un modo conveniente per evitare di dover specificare ripetutamente l'indirizzo IP e la porta. In realtà non fa nulla a livello di rete. Tuttavia, puoi tenere traccia manualmente dei peer con cui stai parlando in UDP. Ma se lo fai, allora decidere che cosa conta come "connessione" è il tuo problema, non il sistema operativo. Se si desidera ristabilire una "connessione" su ogni messaggio, è possibile farlo. Tuttavia, probabilmente non è una buona idea.


9

La mia comprensione è che quando si stabilisce una connessione TCP, tale connessione rimane aperta fino a quando non viene scaduta dall'applicazione o chiusa forzatamente dal server o dal client.

Dal punto di vista di TCP, non esiste client o server (client / server è un concetto di applicazione fuori tema qui). TCP stabilisce una connessione tra peer ed entrambi i peer possono inviare e ricevere sulla connessione fino a quando entrambi i peer non la chiudono o non scade dall'inattività.

I dati inviati tramite questa connessione sono uno stream e non apriranno / chiuderanno nuove connessioni indipendentemente dai 3 V (volume, velocità, varietà).

Ciò che può confondere la situazione è che alcune applicazioni, ad esempio i browser, apriranno connessioni multiple per caricare contemporaneamente elementi come elementi di una pagina Web.

TCP non apre una nuova connessione per ogni segmento che invia, ma un'applicazione può aprire più connessioni TCP. Inoltre, quando una connessione TCP viene chiusa, la porta TCP utilizzata nella connessione viene liberata ed è disponibile per essere riutilizzata. Questa risposta fornisce alcune informazioni e punta all'RFC per TCP.


2
Sebbene in TCP vi sia un partner che ha avviato la connessione (spesso chiamato "client") e l'altro (spesso chiamato "server"). Naturalmente, dopo aver stabilito la connessione, questa differenza non ha più importanza.
Paŭlo Ebermann,

2
@ PaŭloEbermann, non c'è nulla nel RFC TCP su client o server. Il concetto client / server è un concetto di applicazione. Ciò che è in argomento qui sono i protocolli al livello OSI-4 o inferiore, e in quei protocolli non ci sono client o server. In effetti, ciò che si può presumere essere un client (quello che apre una connessione TCP) può, in effetti, essere un server delle applicazioni. Abbiamo server che avviano connessioni TCP ai client per fare cose come controlli di sicurezza e aggiornamenti.
Ron Maupin

7

No, TCP non ha bisogno di aprire una nuova connessione per ogni pacchetto inviato.

È possibile inviare più pacchetti tramite connessioni persistenti HTTP , dove:

... una singola connessione TCP per inviare e ricevere più richieste / risposte HTTP [viene utilizzata], anziché aprire una nuova connessione per ogni singola coppia richiesta / risposta.

In allegato è una figura che mostra la differenza tra più connessioni (molte connessioni stabilite per inviare un oggetto per connessione) e una connessione persistente (una connessione stabilita e più oggetti ivi inviati):

Connessioni multiple vs connessione permanente

Fonte: https://www.vcloudnine.de/how-to-dramatical-improve-website-load-times/


7
Questa risposta sembra essere livelli confusi. Una richiesta / risposta HTTP è raramente un singolo pacchetto.
Barmar,

2
Per non parlare di ogni "aperto" in realtà sono 3 frecce (syn, synack, ack), e ogni "chiusura" è un altro 4 (pinna, ack 2x server e client), quindi se ci fosse effettivamente una connessione per pacchetto, l'overhead si sommerebbe rapidamente.
htmlcoderexe,

5

La tua interpretazione di come funziona TCP è corretta.

Per quanto riguarda quello che ha detto il tuo amico, vedo due possibilità qui:

  1. Hai frainteso il tuo amico, che si riferiva a qualche limitazione a livello di applicazione che comporta l'invio di ogni messaggio su una nuova connessione (e questo non è necessariamente insolito; potrebbe o non essere possibile decidere su questo comportamento, a seconda del software stack che stai utilizzando);

  2. Il tuo amico ha torto.


5

Come altri hanno sottolineato, TCP consente assolutamente a una connessione di rimanere aperta per qualsiasi periodo di tempo, scambiando un numero qualsiasi di "messaggi" in entrambe le direzioni durante quel periodo. Detto questo, dipende in definitiva dalle applicazioni (sia client che server) determinare se tale funzionalità viene utilizzata.

Per riutilizzare la connessione TCP (socket) esistente, l'applicazione client deve tenere aperto quel socket e utilizzarlo quando deve scrivere più dati. Se il client non lo fa, ma invece scarta il vecchio socket e apre un nuovo socket ogni volta che ne ha bisogno, forzerà effettivamente una nuova connessione che potrebbe causare problemi di risorse sul client o sul server se eseguita abbastanza frequentemente da esaurire il pool di connessioni dello stack TCP.

Allo stesso modo, il server deve essere abbastanza intelligente da mantenere il socket aperto su un lato e attendere ulteriori dati. Come il client, ha la possibilità di chiudere il socket a quel punto un client con tolleranza agli errori che desidera inviare più dati non avrà altra scelta che aprire un nuovo socket, portando allo stesso problema.

Infine, come altri hanno già detto, TCP è orientato al flusso. Non c'è alcun tipo di inquadratura. Solo perché un peer ha scritto i dati in un modo particolare (ad esempio 1 chiamata da 1024 byte in scrittura seguita da 2 chiamate in scrittura da 256 byte), ciò non garantisce che l'altro peer lo leggerà in blocchi della stessa dimensione (ad esempio potrebbe ottenere tutti i 1536 byte in una chiamata di lettura). Pertanto, se si inviano più "messaggi" su socket TCP non elaborati, è necessario fornire il proprio protocollo di framing per delineare i diversi messaggi. Sebbene ci siano certamente modi semplici per farlo, è generalmente sconsigliato in quanto ci sono molti protocolli costruiti su TCP per risolvere questo problema. Per ulteriori discussioni, consultare questo: https://blog.stephencleary.com/2009/04/message-framing.html


2

Penso che il tuo amico stesse parlando di HTTP, non di TCP.

HTTP era originariamente un protocollo senza stato: ogni richiesta HTTP utilizzava una connessione TCP separata. Questo è il motivo per cui abbiamo bisogno dei cookie (o qualcosa di simile) per implementare le sessioni.


0

Hai citato "una singola connessione e richiedi una nuova porta ogni volta" e interpreterei come hai molti client che usano la tecnica PAT nello stesso ambiente di rete per connettersi al server esterno alla tua organizzazione. Il PAT avrebbe il limite di 65535 (limite di sessione TCP sull'indirizzo IPv4). Se è vero, hai il limite.

TCP apre una nuova connessione per ogni pacchetto inviato? NO, non finché la sessione TCP è valida. e ...


0

Mi piace l' eccellente pagina di Wikipedia su TCP . Mostra chiaramente cosa succede con il numero di porta. Per caso, contiene anche un utile capitolo sull'uso delle risorse:

Utilizzo delle risorse

La maggior parte delle implementazioni alloca una voce in una tabella che associa una sessione a un processo del sistema operativo in esecuzione. Poiché i pacchetti TCP non includono un identificatore di sessione, entrambi gli endpoint identificano la sessione utilizzando l'indirizzo e la porta del client. Ogni volta che viene ricevuto un pacchetto, l'implementazione TCP deve eseguire una ricerca su questa tabella per trovare il processo di destinazione. Ogni voce nella tabella è nota come blocco di controllo della trasmissione o TCB. Contiene informazioni sugli endpoint (IP e porta), lo stato della connessione, l'esecuzione dei dati sui pacchetti che vengono scambiati e i buffer per l'invio e la ricezione di dati.

Il numero di sessioni sul lato server è limitato solo dalla memoria e può aumentare con l'arrivo di nuove connessioni, ma il client deve allocare una porta casuale prima di inviare il primo SYN al server. Questa porta rimane allocata durante l'intera conversazione e limita efficacemente il numero di connessioni in uscita da ciascuno degli indirizzi IP del client. Se un'applicazione non riesce a chiudere correttamente le connessioni non necessarie, un client può esaurire le risorse e diventare incapace di stabilire nuove connessioni TCP, anche da altre applicazioni.

In breve, TCP utilizza una risorsa molto finita, che è il numero di porte sul client (che è limitato dalla dimensione del campo porta nell'intestazione TCP, 16 bit).

Quindi, TCP è in grado di esaurire le porte, se un client apre molte connessioni TCP in parallelo senza chiuderle. Il problema si verifica solo sul lato client e non importa se le connessioni sono con indirizzi IP o porte server uguali o diversi.

Nella tua impostazione, sembra che tu abbia un'applicazione che accetta molte richieste client ( questepotrebbero essere richieste TCP individuali, poiché forse i tuoi clienti lo usano per registrare alcuni eventi nella tua applicazione e non tenere il canale TCP aperto tra di loro) e creare una nuova richiesta interna al tuo broker Kafka (che molto facilmente potrebbe essere singole connessioni TCP se hai scelto di implementarli in questo modo). In questo caso, il collo di bottiglia (in termini di risorse, non di prestazioni) sarebbe se riesci a ottenere un numero enorme di richieste contemporaneamente dai tuoi clienti (nessun problema per te, dal momento che sul lato server hai bisogno solo di una porta per tutte) e tu apri un numero enorme di richieste in avanti al tuo Kafka e Kafka non è in grado di elaborarle abbastanza velocemente, finendo per avere più connessioni a 16 bit aperte contemporaneamente.

Tu sei il giudice proprio qui; controlla l'applicazione e prova a scoprire se ti connetti a Kafka con una richiesta separata ogni volta (magari tramite un proxy API REST). Se lo fai e hai un numero enorme di clienti, allora sei sicuramente in pericolo.

Se hai solo una manciata di client, meno di 65k-ish e / o mantieni una singola connessione al tuo browser Kafka, allora starai bene.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.