¿TCP abre una nueva conexión para cada paquete que se envía?

15

Esta podría ser una pregunta tonta, pero algunos amigos y yo hemos estado discutiendo las posibles limitaciones de TCP. Tenemos una aplicación que escuchará a los clientes (piense en una puerta de enlace) y enrutará todos los datos de los clientes conectados a través de un único editor de kafka conectado a un tema.

Uno de mis amigos está diciendo que TCP será un problema para esta puerta de enlace porque establecerá una nueva conexión para cada mensaje que envíe (no el kafka, pero el protocolo de transporte subyacente es el problema), lo que requiere un nuevo puerto cada vez. ¿Al ritmo que enviaremos estos mensajes de clientes (gigabytes), kafka se quedará sin puertos para leer?

He desarrollado durante varios años y nunca he oído hablar de esto antes y me gustaría obtener una comprensión de nivel inferior (que pensé que tenía) de cómo funciona TCP. Entiendo que cuando establece una conexión TCP, esa conexión permanece abierta hasta que la aplicación agota el tiempo de espera o el servidor o el cliente la cierran a la fuerza. Los datos que se envían a través de esta conexión son una secuencia y no abrirán / cerrarán nuevas conexiones independientemente de las 3 V (volumen, velocidad, variedad).

En lo que respecta a los puertos, se usa un puerto para la transmisión y el puerto interno del descriptor de archivos es algo que la aplicación administra para la lectura / escritura de clientes individuales. Nunca he entendido que TCP establece nuevas conexiones para cada paquete que escribe.

Pido disculpas de antemano si esta pregunta no es directa o demasiado vaga. Realmente estoy desconcertado y espero que alguien pueda proporcionar más contexto a lo que dicen mis colegas.

user0000001
fuente
13
Creo que has entendido mal lo que decía tu amigo. TCP no hace tal cosa, pero es posible que cierto cliente haga una nueva conexión TCP para cada mensaje que quiera pasar.
hobbs
13
TCP no podría abrir una nueva conexión para cada paquete porque necesita varios paquetes para abrir una nueva conexión. Y no pudo abrir una nueva conexión para cada mensaje porque TCP no tiene el concepto de un mensaje. Tu amigo está muy confundido. Lo más importante que hay que entender sobre TCP, el concepto más fundamental, es que TCP es un protocolo de flujo de bytes.
David Schwartz
1
El argumento de su amigo no es necesariamente incorrecto: si no reutiliza los puertos a través del mantenimiento de nivel de aplicación o simplemente hay demasiados clientes, su sistema puede quedarse sin puertos efímeros. Hay formas de solucionar ese problema: usar SO_REUSEADDRpara cerrar sockets más rápido, aumentar el rango de puertos efímeros, etc. Además, TCP_FASTOPENse pueden usar varios conmutadores a nivel del sistema operativo para solucionar otras limitaciones bien conocidas de TCP. De cualquier manera, no tiene sentido discutir las limitaciones de TCP cuando ni siquiera tiene una carga de trabajo para probar.
user1643723

Respuestas:

22

Uno de mis amigos está diciendo que TCP será un problema para esta puerta de enlace porque establecerá una nueva conexión para cada mensaje que envíe (no el kafka, pero el protocolo de transporte subyacente es el problema), lo que requiere un nuevo puerto cada vez. ¿Al ritmo que enviaremos estos mensajes de clientes (gigabytes), kafka se quedará sin puertos para leer?

Tu amigo está muy confundido. TCP es un protocolo orientado a la transmisión. No tiene noción de mensajes. Por supuesto, usa paquetes en la capa IP, pero para la aplicación esto es un detalle de implementación. TCP inserta límites de paquetes donde tiene sentido hacerlo, y no necesariamente una vez por write()osend() . Del mismo modo, combina paquetes sucesivos si recibe más de uno entre llamadas read()ao recv().

No hace falta decir que este diseño orientado a la transmisión sería completamente inviable si cada envío estableciera una nueva conexión. Por lo tanto, la única forma de establecer una nueva conexión es cerrar y volver a abrir la conexión manualmente.

(En la práctica, la mayoría de los protocolos creados sobre TCP tienen algo parecido a mensajes, como solicitudes y respuestas HTTP. Pero TCP no conoce ni se preocupa por las estructuras de tales cosas).

Es posible que su amigo estuviera pensando en UDP, que tiene mensajes, pero también no tiene conexión. La mayoría de las implementaciones de socket le permiten "conectar" un socket UDP a un host remoto, pero esta es solo una manera conveniente de evitar tener que especificar repetidamente la dirección IP y el puerto. En realidad, no hace nada a nivel de red. Sin embargo, puede realizar un seguimiento manual de los pares con los que está hablando en UDP. Pero si hace eso, entonces decidir qué cuenta como una "conexión" es su problema, no el sistema operativo. Si desea restablecer una "conexión" en cada mensaje, puede hacerlo. Sin embargo, probablemente no sea una muy buena idea.

Kevin
fuente
9

Entiendo que cuando establece una conexión TCP, esa conexión permanece abierta hasta que la aplicación agota el tiempo de espera o el servidor o el cliente la cierran a la fuerza.

Desde la perspectiva de TCP, no hay cliente o servidor (cliente / servidor es un concepto de aplicación que está fuera de tema aquí). TCP establece una conexión entre pares, y ambos pares pueden enviar y recibir en la conexión hasta que un par la cierre o se agote el tiempo de inactividad.

Los datos que se envían a través de esta conexión son una secuencia y no abrirán / cerrarán nuevas conexiones independientemente de las 3 V (volumen, velocidad, variedad).

Lo que puede confundir la situación es que algunas aplicaciones, por ejemplo, navegadores, abrirán múltiples conexiones para cargar simultáneamente elementos como elementos de una página web.

TCP no abre una nueva conexión para cada segmento que envía, pero una aplicación puede abrir múltiples conexiones TCP. Además, cuando se cierra una conexión TCP, el puerto TCP utilizado en la conexión se libera y está disponible para ser utilizado nuevamente. Esta respuesta proporciona cierta información y le señala el RFC para TCP.

Ron Maupin
fuente
2
Aunque en TCP hay un socio que inició la conexión (a menudo llamado "cliente") y el otro (a menudo llamado "servidor"). Por supuesto, una vez establecida la conexión, esta diferencia ya no importa.
Paŭlo Ebermann
2
@ PaŭloEbermann, no hay nada en el TCP RFC sobre clientes o servidores. El concepto de cliente / servidor es un concepto de aplicación. Lo que trata el tema aquí es protocolos en OSI o por debajo de la capa 4, y no hay clientes o servidores en esos protocolos. De hecho, lo que puede suponer que es un cliente (el que abre una conexión TCP) puede, de hecho, ser un servidor de aplicaciones. Tenemos servidores que inician conexiones TCP a clientes para hacer cosas como controles de seguridad y actualizaciones.
Ron Maupin
7

No, TCP no necesita abrir una nueva conexión para cada paquete que se envía.

Puede enviar múltiples paquetes a través de conexiones persistentes HTTP , donde:

... se utiliza una única conexión TCP para enviar y recibir múltiples solicitudes / respuestas HTTP [en lugar de abrir una nueva conexión para cada par de solicitud / respuesta.

Se adjunta una figura que muestra la diferencia entre múltiples conexiones (muchas conexiones establecidas para enviar un objeto por conexión) y una conexión persistente (una conexión establecida y múltiples objetos enviados allí):

Múltiples conexiones vs conexión persistente

Fuente: https://www.vcloudnine.de/how-to-dramatic-improve-website-load-times/


fuente
77
Esta respuesta parece ser capas confusas. Una solicitud / respuesta HTTP rara vez es un solo paquete.
Barmar
2
Sin mencionar que cada "apertura" es en realidad 3 flechas (syn, synack, ack), y cada "cierre" es otro 4 (fin, ack 2x servidor y cliente), por lo que si realmente hubiera una conexión por paquete, la sobrecarga se sumaría rápidamente
htmlcoderexe
5

Su interpretación de cómo funciona TCP es correcta.

En cuanto a lo que dijo tu amigo, veo dos posibilidades aquí:

  1. No entendió bien a su amigo, que se refería a una limitación de la capa de aplicación que hace que cada mensaje se envíe a través de una nueva conexión (y esto no es necesariamente inusual; puede o no ser posible decidir sobre este comportamiento, dependiendo de qué software pila que estás usando);

  2. Tu amigo está equivocado.

La ligereza corre con Mónica
fuente
5

Como otros han señalado, TCP absolutamente permite que una conexión permanezca abierta durante cualquier cantidad de tiempo, intercambiando cualquier cantidad de "mensajes" en cualquier dirección durante ese tiempo. Dicho esto, en última instancia, depende de las aplicaciones (tanto del cliente como del servidor) determinar si se utiliza esa capacidad.

Para reutilizar la conexión TCP (socket) existente, la aplicación cliente debe mantener ese socket abierto y usarlo cuando necesite escribir más datos. Si el cliente no hace esto, pero en su lugar descarta el socket antiguo y abre un socket nuevo cada vez que lo necesita, entonces forzará una nueva conexión que podría causar problemas de recursos en el cliente o el servidor si se hace con la frecuencia suficiente para agotar o bien el grupo de conexiones de la pila TCP.

Del mismo modo, el servidor debe ser lo suficientemente inteligente como para mantener el socket abierto a su lado y esperar más datos. Al igual que el cliente, tiene la opción de cerrar el socket, en cuyo punto un cliente tolerante a fallas que desee enviar más datos no tendrá más remedio que abrir un nuevo socket, lo que lleva al mismo problema.

Finalmente, como otros han mencionado, TCP está orientado a la transmisión. No hay encuadre en absoluto. El hecho de que un par escribiera los datos de una manera particular (por ejemplo, una llamada de escritura de 1 1024 bytes seguida de una llamada de escritura de 2 256 bytes), eso no garantiza que el otro par los lea en fragmentos del mismo tamaño (por ejemplo, podría obtener los 1536 bytes en una llamada de lectura). Por lo tanto, si envía múltiples "mensajes" a través de sockets TCP sin procesar, debe proporcionar su propio protocolo de trama para delinear los diferentes mensajes. Si bien existen formas sencillas de hacerlo, generalmente no es aconsejable, ya que hay muchos protocolos integrados sobre TCP para resolver este problema. Para mayor discusión, consulte esto: https://blog.stephencleary.com/2009/04/message-framing.html

escocés
fuente
2

Creo que tu amigo estaba hablando de HTTP, no de TCP.

HTTP era originalmente un protocolo sin estado: cada solicitud HTTP usaría una conexión TCP separada. Es por eso que necesitamos cookies (o algo similar) para implementar sesiones.

reinierpost
fuente
0

Usted ha mencionado "conexión única y requiere un nuevo puerto cada vez", y yo interpretaría que tiene muchos clientes que utilizan la técnica PAT en el mismo entorno de red para conectarse al servidor fuera de su organización. El PAT tendría el límite de 65535 (límite de sesión TCP en la dirección IPv4). Si es cierto, tienes el límite.

¿TCP abre una nueva conexión para cada paquete que se envía? NO, no lo hace mientras la sesión TCP sea válida. y ...

Hola
fuente
0

Me gusta la excelente página de Wikipedia en TCP . Muestra claramente lo que sucede con el número de puerto. Por casualidad, también contiene un capítulo útil sobre el uso de recursos:

El uso de recursos

La mayoría de las implementaciones asignan una entrada en una tabla que asigna una sesión a un proceso del sistema operativo en ejecución. Dado que los paquetes TCP no incluyen un identificador de sesión, ambos puntos finales identifican la sesión utilizando la dirección y el puerto del cliente. Cada vez que se recibe un paquete, la implementación de TCP debe realizar una búsqueda en esta tabla para encontrar el proceso de destino. Cada entrada en la tabla se conoce como Bloque de control de transmisión o TCB. Contiene información sobre los puntos finales (IP y puerto), estado de la conexión, datos de ejecución sobre los paquetes que se intercambian y almacenamientos intermedios para enviar y recibir datos.

El número de sesiones en el lado del servidor está limitado solo por la memoria y puede crecer a medida que llegan nuevas conexiones, pero el cliente debe asignar un puerto aleatorio antes de enviar el primer SYN al servidor. Este puerto permanece asignado durante toda la conversación y limita efectivamente el número de conexiones salientes de cada una de las direcciones IP del cliente. Si una aplicación no cierra correctamente las conexiones no requeridas, un cliente puede quedarse sin recursos y no puede establecer nuevas conexiones TCP, incluso desde otras aplicaciones.

En resumen, TCP utiliza un recurso muy finito, que es el número de puertos en el cliente (que está limitado por el tamaño del campo de puerto en el encabezado TCP, 16 bits).

Por lo tanto, TCP es capaz de ejecutar fuera de los puertos, si un cliente abre una gran cantidad de conexiones TCP en paralelo sin cerrarlos. El problema solo ocurre en el lado del cliente, y no importa si las conexiones son con la misma o diferentes direcciones IP o puertos del servidor.

En su configuración, parece tener una aplicación que acepta muchas solicitudes de clientes ( estaspodrían ser solicitudes TCP individuales, ya que tal vez sus clientes usen esto para registrar algunos eventos en su aplicación y no mantengan el canal TCP abierto en el medio), y crear una nueva solicitud interna a su agente Kafka (que muy fácilmente podría ser conexiones TCP individuales si elige implementarlos así). En este caso, el cuello de botella (en términos de recursos, no de rendimiento) sería si logras obtener un gran número de solicitudes al mismo tiempo de tus clientes (no hay problema para ti, ya que en el lado del servidor solo necesitas un puerto para todos ellos), y abres una gran cantidad de solicitudes de reenvío a tu Kafka, y Kafka no puede procesarlas lo suficientemente rápido, terminando con que tienes más de 16 bits de conexiones abiertas al mismo tiempo.

Eres el propio juez aquí; compruebe su aplicación e intente averiguar si se está conectando a Kafka con una solicitud por separado cada vez (tal vez a través de algún proxy REST API). Si lo hace, y tiene un gran número de clientes, entonces ciertamente está en peligro.

Si solo tiene un puñado de clientes, menos de 65k-ish, y / o mantiene una sola conexión a su navegador Kafka, entonces estará bien.

AnoE
fuente