Como o TIME_WAIT do lado do servidor realmente funciona?

11

Eu sei que existem algumas perguntas sobre SE e acredito que li tantas delas quanto antes antes de chegar a esse ponto.

Por "lado do servidor TIME_WAIT", quero dizer o estado de um par de soquetes do lado do servidor que teve seu close () iniciado no lado do servidor.

Costumo ver estas afirmações que me parecem contraditórias:

  1. O lado do servidor TIME_WAITé inofensivo
  2. Você deve projetar seus aplicativos de rede para que os clientes iniciem close (), fazendo com que o cliente suporte os TIME_WAIT

A razão pela qual considero isso contraditório é porque TIME_WAITo cliente pode ser um problema - o cliente pode ficar sem portas disponíveis; portanto, em essência, o acima recomendado é transferir a carga do TIME_WAITlado do cliente para onde ele pode ser um problema, a partir do lado do servidor onde não é um problema.

TIME_WAITObviamente, o lado do cliente é apenas um problema para um número limitado de casos de uso. A maioria das soluções cliente-servidor envolveria um servidor e muitos clientes. Geralmente, os clientes não lidam com um volume de conexões suficientemente alto para que isso seja um problema e, mesmo se o fizerem, há várias recomendações para "sanear". em oposição a SO_LINGERcom tempo limite 0, ou se intrometendo com tcp_tw sysctls) combate o lado do cliente, TIME_WAITevitando criar muitas conexões muito rapidamente. Mas isso nem sempre é viável, por exemplo, para classes de aplicativos como:

  • sistemas de monitoramento
  • geradores de carga
  • proxies

Por outro lado, eu nem entendo como o lado do servidor TIME_WAITé útil. O motivo TIME_WAITestá aí, porque evita a injeção de TCPfragmentos obsoletos em fluxos aos quais eles não pertencem mais. Para o lado do cliente, TIME_WAITisso é feito simplesmente impossibilitando a criação de uma conexão com os mesmos ip:portpares que essa conexão obsoleta poderia ter (os pares usados ​​são bloqueados por TIME_WAIT). Mas para o servidor, isso não pode ser evitado, pois o endereço local terá a porta de aceitação e sempre será o mesmo, e o servidor não pode (AFAIK, eu tenho apenas a prova empírica) negar a conexão simplesmente porque um ponto de entrada criaria o mesmo par de endereços que já existe na tabela de soquetes.

Eu escrevi um programa que mostra que o TIME-WAIT do lado do servidor é ignorado. Além disso, como o teste foi realizado no 127.0.0.1, o kernel deve ter um bit especial que informa se é do lado do servidor ou do cliente (caso contrário, a tupla seria a mesma).

Fonte: http://pastebin.com/5PWjkjEf , testado no Fedora 22, configuração de rede padrão.

$ gcc -o rtest rtest.c -lpthread
$ ./rtest 44400 s # will do server-side close
Will initiate server close
... iterates ~20 times successfully
^C
$ ss -a|grep 44400
tcp    TIME-WAIT  0      0            127.0.0.1:44400         127.0.0.1:44401   
$ ./rtest 44500 c # will do client-side close
Will initiate client close
... runs once and then
connecting...
connect: Cannot assign requested address

Portanto, para o lado do servidor TIME_WAIT, as conexões exatamente no mesmo par de portas podem ser restabelecidas imediatamente e com êxito e, para o lado do cliente TIME-WAIT, na segunda iteração, a connect()falha com retidão

Para resumir, a pergunta é dupla:

  • O lado do servidor TIME_WAITrealmente não faz nada e é deixado assim porque o RFCrequer?
  • É por isso que a recomendação é que o cliente inicie close () porque o servidor TIME_WAITé inútil?
Pawel Veselov
fonte
Você não ficará sem portas a menos que tenha apenas 1 cliente. Você tem 65535 portas para cada combinação de IP do cliente / servidor. A conexão de 1.2.3.4:1111 é diferente de 4.3.2.1:1111. Leva apenas alguns bytes de memória para cada conexão TIME_WAIT.
Marki555 21/05

Respostas:

1

Em termos de TCP , lado do servidor aqui significa o host que possui o soquete no estado LISTEN.

O RFC1122 permite que o soquete no estado TIME-WAIT aceite uma nova conexão com algumas condições

        When a connection is closed actively, it MUST linger in
        TIME-WAIT state for a time 2xMSL (Maximum Segment Lifetime).
        However, it MAY accept a new SYN from the remote TCP to
        reopen the connection directly from TIME-WAIT state, if it:

Para detalhes exatos sobre as condições, consulte o RFC1122 . Eu esperaria que também deve haver um OPEN passivo correspondente no soquete (soquete no estado LISTEN).

O OPEN ativo (chamada de conexão do lado do cliente) não possui essa exceção e deve dar erro quando o soquete estiver no TIME-WAIT, conforme RFC793 .

Meu palpite para a recomendação do cliente (em termos de TCP, o host executando OPEN ativo, isto é, conectar) iniciado próximo é praticamente o mesmo que o seu, que, no caso comum, ele espalha os soquetes TIME-WAIT em mais hosts, onde há abundância de recursos para as tomadas. No caso comum, os clientes não enviam SYN que reutilizariam os soquetes TIME-WAIT no servidor. Concordo que a aplicação de tal recomendação ainda depende do caso de uso.

Marko Kohtala
fonte
0

Este é provavelmente o exemplo mais claro do que o TIME-WAIT realmente faz e, mais importante, por que é importante. Ele também explica por que evitar algumas dicas 'especializadas' em máquinas Linux para 'reduzir' o tempo de espera.

Khushil
fonte
Ainda não explica o que acontece quando um client-> conexão com o servidor é iniciado, e um servidor tem que par bloqueado em um TIME_WAIT
Pawel Veselov
Consulte stackoverflow.com/questions/1490196/… - a resposta existe o que você está procurando.
Khushil 9/07/2015
0

Uma sessão tcp é identificada pelo tupple (sourceIP, sourcePort, destIP, destPort). Portanto, o TIME_WAIT funciona em todas as conexões TCP.

Em relação ao lado de fechamento, em alguns cenários, o fechamento do lado do cliente pode reduzir os soquetes TIME_WAIT no servidor, reduzindo um pouco a memória. Nos casos em que o espaço do soquete pode ser esgotado (devido ao esgotamento efêmero da porta) (por exemplo, clientes gananciosos com muitas conexões com o mesmo servidor), esse problema deve ser resolvido de qualquer lado.

basos
fonte
Por favor explique; Quando você pergunta se o TW do lado do servidor faz alguma coisa, você se pergunta se a mesma conexão pode ser reutilizada durante o período do TW. A resposta é não, porque a conexão, conforme definida pelo tupple, ocorre na tabela tcp do servidor. Se o cliente tentar abrir a mesma conexão em breve, ele receberá um RST, negando efetivamente a conexão tcp. A propósito, o artigo de Khushil é muito descritivo.
basos 20/08/2015
Sinto muito, sua resposta realmente responde à pergunta, eu a li errado e retraí meu comentário. No entanto, também parece estar incorreto, pois tenho um código que parece provar que não há proteção do lado do servidor TIME_WAIT(atualizei a pergunta com essas informações). A referência do @ Khushil não cobre TIME_WAITcasos do lado do servidor com detalhes suficientes.
Pawel Veselov
-2

Você nunca pode ter certeza, com um protocolo não confiável, de que recebeu a última mensagem do seu dispositivo ponto a ponto, portanto, é perigoso supor que ele tenha desligado o telefone repentinamente. É uma grande desvantagem do protocolo TCP que apenas 65000 ou mais portas possam ser abertas simultaneamente. Mas a maneira de superar isso seria mudar para um farm de servidores, que se adapta melhor à carga, do que reciclando números de portas rapidamente. No final do cliente, é altamente improvável que você fique sem portas se for uma estação de trabalho básica.

jrrk
fonte
Sinto muito, mas isso não responde à minha pergunta.
Pawel Veselov