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?
fonte
SO_REUSEADDR
para fechar soquetes mais rapidamente, aumentar o intervalo de portas efêmeras etc. Além disso,TCP_FASTOPEN
vá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.Respostas:
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 pararead()
ourecv()
.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.
fonte
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.
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.
fonte
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:
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):
Fonte: https://www.vcloudnine.de/how-to-dramatically-improve-website-load-times/
fonte
Sua interpretação de como o TCP funciona está correta.
Quanto ao que seu amigo disse, vejo duas possibilidades aqui:
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);
Seu amigo está errado.
fonte
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
fonte
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.
fonte
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 ...
fonte
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:
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.
fonte