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.
fuente
SO_REUSEADDR
para cerrar sockets más rápido, aumentar el rango de puertos efímeros, etc. Además,TCP_FASTOPEN
se 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.Respuestas:
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 llamadasread()
aorecv()
.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.
fuente
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.
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.
fuente
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 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í):
Fuente: https://www.vcloudnine.de/how-to-dramatic-improve-website-load-times/
fuente
Su interpretación de cómo funciona TCP es correcta.
En cuanto a lo que dijo tu amigo, veo dos posibilidades aquí:
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);
Tu amigo está equivocado.
fuente
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
fuente
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.
fuente
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 ...
fuente
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:
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.
fuente