O TCP abre uma nova conexão para cada pacote enviado?

15

Essa pode ser uma pergunta boba, mas eu e poucos amigos discutimos as possíveis limitações do TCP. Temos um aplicativo que escuta clientes (pense em um gateway) e roteia todos os dados de clientes conectados por meio de um único editor kafka conectado a um tópico.

Um dos meus amigos está dizendo que o TCP será um problema para esse gateway, pois estabelecerá uma nova conexão para cada mensagem que enviar (não o kafka, mas o próprio protocolo de transporte subjacente), exigindo uma nova porta a cada vez. Na velocidade em que estaremos enviando mensagens para esses clientes (gigabytes), o kafka ficará sem portas para ler?

Eu desenvolvi o desenvolvimento por vários anos e nunca ouvi falar disso antes e gostaria de obter um entendimento de nível mais baixo (que eu pensava ter) de como o TCP funciona. Meu entendimento é que, quando você estabelece uma conexão TCP, essa conexão permanece aberta até que o tempo limite seja atingido pelo aplicativo ou forçado a fechar pelo servidor ou pelo cliente. Os dados enviados por essa conexão são um fluxo e não abrem / fecham novas conexões, independentemente dos 3 Vs (volume, velocidade, variedade).

No que diz respeito às portas, uma porta é usada para transmissão e a porta interna do descritor de arquivo é algo que o aplicativo gerencia para leitura / gravação de clientes individuais. Eu nunca entendi o TCP para estabelecer novas conexões para cada pacote que ele escreve.

Peço desculpas antecipadamente se esta pergunta não for direta e / ou vaga. Estou realmente confuso e espero que alguém possa fornecer um pouco mais de contexto ao que meus colegas estão dizendo?

user0000001
fonte
13
Acho que você não entendeu o que seu amigo estava dizendo. O TCP não faz isso, mas é possível que um determinado cliente faça uma nova conexão TCP para cada mensagem que deseja passar.
hobbs
13
O TCP não pôde abrir uma nova conexão para cada pacote porque ele precisa de vários pacotes para abrir uma nova conexão. E não foi possível abrir uma nova conexão para cada mensagem porque o TCP não tem conceito de mensagem. Seu amigo está muito confuso. A coisa mais importante a entender sobre o TCP, o conceito mais fundamental, é que o TCP é um protocolo de fluxo de bytes.
David Schwartz
1
O argumento do seu amigo não está necessariamente errado - se você não reutilizar portas via keep-alive no nível do aplicativo ou houver simplesmente muitos clientes, seu sistema pode ficar sem portas efêmeras. Existem maneiras de contornar esse problema: usar SO_REUSEADDRpara fechar soquetes mais rapidamente, aumentar o intervalo de portas efêmeras etc. Além disso, TCP_FASTOPENvárias alternâncias no nível do sistema operacional podem ser usadas para solucionar outras limitações conhecidas do TCP. De qualquer maneira, não há sentido em discutir as limitações do TCP quando você nem sequer tem uma carga de trabalho para testar.
user1643723

Respostas:

22

Um dos meus amigos está dizendo que o TCP será um problema para esse gateway, pois estabelecerá uma nova conexão para cada mensagem que enviar (não o kafka, mas o próprio protocolo de transporte subjacente), exigindo uma nova porta a cada vez. Na velocidade em que estaremos enviando mensagens para esses clientes (gigabytes), o kafka ficará sem portas para ler?

Seu amigo está muito confuso. TCP é um protocolo orientado a fluxo. Não tem noção de mensagens. Obviamente, ele usa pacotes na camada IP, mas para o aplicativo esse é um detalhe de implementação. O TCP insere limites de pacotes onde faz sentido, e não necessariamente uma vez por write()ousend() . Da mesma forma, ele combina pacotes sucessivos se você receber mais de um entre chamadas para read()ou recv().

Desnecessário dizer que esse design orientado ao fluxo seria completamente impraticável se cada envio estabelecesse uma nova conexão. Portanto, a única maneira de estabelecer uma nova conexão é fechar e reabrir a conexão manualmente.

(Na prática, a maioria dos protocolos criados sobre o TCP tem algo parecido com mensagens, como solicitações e respostas HTTP. Mas o TCP não conhece nem se importa com as estruturas de tais coisas.)

É possível que seu amigo estivesse pensando em UDP, que possui mensagens, mas também não possui conexão. A maioria das implementações de soquete permite "conectar" um soquete UDP a um host remoto, mas essa é apenas uma maneira conveniente de evitar a necessidade de especificar repetidamente o endereço IP e a porta. Na verdade, ele não faz nada no nível da rede. No entanto, você pode acompanhar manualmente os colegas com quem está falando no UDP. Mas se você fizer isso, decidir o que conta como "conexão" é um problema seu, não o sistema operacional. Se você deseja restabelecer uma "conexão" em todas as mensagens, você pode fazer isso. Provavelmente não é uma ideia muito boa, no entanto.

Kevin
fonte
9

Meu entendimento é que, quando você estabelece uma conexão TCP, essa conexão permanece aberta até que o tempo limite seja atingido pelo aplicativo ou forçado a fechar pelo servidor ou pelo cliente.

Da perspectiva do TCP, não há cliente ou servidor (cliente / servidor é um conceito de aplicativo que está fora do tópico aqui). O TCP estabelece uma conexão entre os pares, e os dois podem enviar e receber na conexão até que o ponto a feche ou o tempo limite da inatividade.

Os dados enviados por essa conexão são um fluxo e não abrem / fecham novas conexões, independentemente dos 3 Vs (volume, velocidade, variedade).

O que pode estar confundindo a situação é que alguns aplicativos, por exemplo, navegadores, abrirão várias conexões para carregar simultaneamente coisas como elementos de uma página da web.

O TCP não abre uma nova conexão para cada segmento enviado, mas um aplicativo pode abrir várias conexões TCP. Além disso, quando uma conexão TCP é fechada, a porta TCP usada na conexão é liberada e fica disponível para uso novamente. Esta resposta fornece algumas informações e aponta para o RFC para TCP.

Ron Maupin
fonte
2
Embora no TCP exista um parceiro que iniciou a conexão (geralmente chamada "cliente") e o outro (geralmente chamado "servidor"). Obviamente, depois que a conexão é estabelecida, essa diferença não importa mais.
Paŭlo Ebermann 14/03/19
2
@ PaEloEbermann, não há nada no TCP RFC sobre clientes ou servidores. O conceito de cliente / servidor é um conceito de aplicativo. O que está em tópico aqui são protocolos na camada 4 da OSI ou abaixo da OSI e não há clientes ou servidores nesses protocolos. De fato, o que você pode assumir como um cliente (aquele que abre uma conexão TCP) pode, de fato, ser um servidor de aplicativos. Temos servidores que iniciam conexões TCP com clientes para fazer coisas como verificações e atualizações de segurança.
Ron Maupin
7

Não, o TCP não precisa abrir uma nova conexão para cada pacote enviado.

Você pode enviar vários pacotes por meio de conexões persistentes HTTP , em que:

... uma única conexão TCP para enviar e receber várias solicitações / respostas HTTP [é usada], em vez de abrir uma nova conexão para cada par de solicitação / resposta.

Em anexo está uma figura que mostra a diferença entre várias conexões (muitas conexões estabelecidas para enviar um objeto por conexão) e uma conexão persistente (uma conexão estabelecida e vários objetos enviados):

Conexões Múltiplas vs Conexão Persistente

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


fonte
7
Esta resposta parece ser camadas confusas. Uma solicitação / resposta HTTP raramente é um único pacote.
Barmar
2
Sem mencionar que todo "aberto" é na verdade três setas (syn, synack, ack), e todo "fechamento" é outro 4 (servidor, cliente e cliente 2x) e, portanto, se houver realmente uma conexão por pacote, a sobrecarga aumentaria rapidamente.
Htmlcoderexe 14/0318
5

Sua interpretação de como o TCP funciona está correta.

Quanto ao que seu amigo disse, vejo duas possibilidades aqui:

  1. Você entendeu mal o seu amigo, que estava se referindo a alguma limitação da camada de aplicativo que resulta em cada mensagem sendo enviada por uma nova conexão (e isso não é necessariamente incomum; pode ou não ser possível decidir sobre esse comportamento, dependendo de qual software pilha que você está usando);

  2. Seu amigo está errado.

Corridas de leveza com Monica
fonte
5

Como outros já apontaram, o TCP absolutamente permite que uma conexão permaneça aberta por qualquer período de tempo, trocando qualquer número de "mensagens" em qualquer direção durante esse período. Dito isso, cabe aos aplicativos (cliente e servidor) determinar se esse recurso é utilizado.

Para reutilizar a conexão TCP existente (soquete), o aplicativo cliente deve manter esse soquete aberto e usá-lo quando precisar gravar mais dados. Se o cliente não fizer isso, mas descartar o soquete antigo e abrir um novo soquete toda vez que precisar de um, forçará uma nova conexão que poderá causar problemas de recursos no cliente ou no servidor se for feita com freqüência suficiente para esgotar o conjunto de conexões da pilha TCP.

Da mesma forma, o servidor deve ser inteligente o suficiente para manter o soquete aberto e aguardar mais dados. Como o cliente, ele tem a opção de fechar o soquete; nesse momento, um cliente tolerante a falhas que deseja enviar mais dados não terá escolha a não ser abrir um novo soquete, levando ao mesmo problema.

Finalmente, como outros já mencionaram, o TCP é orientado para o fluxo. Não existe nenhum enquadramento. Só porque um par escreveu os dados de uma maneira específica (por exemplo, uma chamada de gravação de 1024 bytes seguida por duas chamadas de gravação de 256 bytes), isso não garante que o outro ponto a leia nos mesmos blocos de tamanho (por exemplo, pode obter todos os 1536 bytes em uma chamada de leitura). Portanto, se você estiver enviando várias "mensagens" por soquetes TCP não processados, precisará fornecer seu próprio protocolo de enquadramento para delinear as diferentes mensagens. Embora certamente haja maneiras simples de fazer isso, geralmente é desaconselhável, pois existem muitos protocolos criados no TCP para resolver esse problema. Para uma discussão mais aprofundada, consulte: https://blog.stephencleary.com/2009/04/message-framing.html

Scot
fonte
2

Acho que seu amigo estava falando sobre HTTP, não sobre TCP.

O HTTP era originalmente um protocolo sem estado: cada solicitação HTTP usaria uma conexão TCP separada. É por isso que precisamos de cookies (ou algo semelhante) para implementar sessões.

reinierpost
fonte
0

Você mencionou "conexão única e exige uma nova porta a cada vez", e eu interpretaria como você tem muitos clientes usando a técnica PAT no mesmo ambiente de rede para se conectar ao servidor fora da sua organização. O PAT teria o limite de 65535 (limite de sessão TCP no endereço IPv4). Se for verdade, você tem o limite.

O TCP abre uma nova conexão para cada pacote enviado? NÃO, não enquanto a sessão TCP for válida. e ...

Olá
fonte
0

Gosto da excelente página da Wikipedia sobre TCP . Mostra claramente o que acontece com o número da porta. Por acaso, também contém um capítulo útil sobre o uso de recursos:

Uso de recursos

A maioria das implementações aloca uma entrada em uma tabela que mapeia uma sessão para um processo do sistema operacional em execução. Como os pacotes TCP não incluem um identificador de sessão, os dois pontos de extremidade identificam a sessão usando o endereço e a porta do cliente. Sempre que um pacote é recebido, a implementação do TCP deve executar uma pesquisa nesta tabela para encontrar o processo de destino. Cada entrada na tabela é conhecida como Bloco de controle de transmissão ou TCB. Ele contém informações sobre os pontos de extremidade (IP e porta), status da conexão, dados em execução sobre os pacotes que estão sendo trocados e buffers para enviar e receber dados.

O número de sessões no lado do servidor é limitado apenas pela memória e pode aumentar à medida que novas conexões chegam, mas o cliente deve alocar uma porta aleatória antes de enviar o primeiro SYN para o servidor. Essa porta permanece alocada durante toda a conversa e limita efetivamente o número de conexões de saída de cada um dos endereços IP do cliente. Se um aplicativo falhar em fechar corretamente as conexões não necessárias, um cliente poderá ficar sem recursos e não conseguir estabelecer novas conexões TCP, mesmo de outros aplicativos.

Em resumo, o TCP utiliza um recurso muito finito, que é o número de portas no cliente (limitado pelo tamanho do campo de porta no cabeçalho TCP, 16 bits).

Assim, o TCP é capaz de executar fora de portas, se um cliente abre uma série de conexões TCP em paralelo, sem fechá-los. O problema ocorre apenas no lado do cliente e não importa se as conexões estão com os mesmos endereços IP ou portas de servidor iguais ou diferentes.

Na sua configuração, você parece ter um aplicativo que recebe muitas solicitações de clientes ( essaspodem ser solicitações TCP individuais, pois talvez seus clientes usem isso para registrar alguns eventos em seu aplicativo e não manter o canal TCP aberto entre elas) e criar uma nova solicitação interna para seu broker Kafka (que facilmente poderia ser conexões TCP individuais se você optar por implementá-los assim). Nesse caso, o gargalo (em termos de recursos, e não de desempenho) seria se você conseguir receber um grande número de solicitações ao mesmo tempo de seus clientes (não há problema para você, pois no lado do servidor você precisa apenas de uma porta para todos eles) e você abre um grande número de solicitações de encaminhamento ao seu Kafka, e o Kafka não é capaz de processá-las com rapidez suficiente, resultando em você tendo mais de 16 bits de conexões abertas simultaneamente.

Você é o próprio juiz aqui; verifique seu aplicativo e tente descobrir se você está se conectando ao Kafka com uma solicitação separada a cada vez (talvez por meio de algum proxy da API REST). Se você fizer isso e tiver um grande número de clientes, certamente estará em perigo.

Se você tiver apenas alguns clientes com menos de 65k-ish e / ou manter uma conexão única com o navegador Kafka, ficará bem.

AnoE
fonte