¿Cómo funciona realmente `TIME_WAIT` del lado del servidor?

¿Cómo funciona realmente `TIME_WAIT` del lado del servidor?

Sé que hay bastantes preguntas de SE sobre esto, y creo que leí tantas como sea necesario antes de llegar a este punto.

Por "lado del servidor TIME_WAIT" me refiero al estado de un par de sockets del lado del servidor cuyo cierre() se inició en el lado del servidor.

A menudo veo estas afirmaciones que me suenan contradictorias:

  1. El lado del servidor TIME_WAITes inofensivo
  2. Debe diseñar sus aplicaciones de red para que los clientes inicien close(), por lo tanto, hacer que el cliente lleve laTIME_WAIT

La razón por la que encuentro esto contradictorio es porque TIME_WAITen el cliente puede haber un problema: el cliente puede quedarse sin puertos disponibles, por lo que, en esencia, lo anterior recomienda trasladar la carga TIME_WAITal lado del cliente, donde puede haber un problema, desde el lado del servidor donde no es un problema.

TIME_WAITPor supuesto, el lado del cliente es sólo un problema para un número limitado de casos de uso. La mayoría de las soluciones cliente-servidor involucrarían un servidor y muchos clientes, los clientes generalmente no manejan un volumen de conexiones lo suficientemente alto como para que sea un problema, e incluso si lo hacen, hay una serie de recomendaciones para "sensatamente" ( en lugar de SO_LINGERtener 0 tiempos de espera o interferir con tcp_tw sysctls) combate el lado del cliente TIME_WAITevitando crear demasiadas conexiones demasiado rápido. Pero eso no siempre es factible, por ejemplo para aplicaciones como:

  • sistemas de monitoreo
  • generadores de carga
  • apoderados

Por otro lado, ni siquiera entiendo cómo TIME_WAITes útil el lado del servidor. La razón TIME_WAITincluso está ahí, porque evita inyectar TCPfragmentos obsoletos en secuencias a las que ya no pertenecen. Para el lado del cliente, TIME_WAITesto se logra simplemente haciendo imposible crear una conexión con los mismos ip:portpares que podría haber tenido esta conexión obsoleta (los pares usados ​​están bloqueados por TIME_WAIT). Pero para el lado del servidor, esto no se puede evitar ya que la dirección local tendrá el puerto de aceptación y siempre será la misma, y ​​el servidor no puede (AFAIK, solo tengo la prueba empírica) negar la conexión simplemente porque un par entrante crearía el mismo par de direcciones que ya existe en la tabla de sockets.

Escribí un programa que muestra que se ignoran los tiempos de espera del lado del servidor. Además, debido a que la prueba se realizó en 127.0.0.1, el kernel debe tener un bit especial que incluso le indique si es del lado del servidor o del lado del cliente (ya que de lo contrario la tupla sería la misma).

Fuente:http://pastebin.com/5PWjkjEf, probado en Fedora 22, configuración de red predeterminada.

$ 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

Entonces, para el lado del servidor TIME_WAIT, las conexiones en exactamente el mismo par de puertos podrían restablecerse inmediatamente y con éxito, y para el lado del cliente TIME-WAIT, en la segunda iteración connect()falló justamente.

En resumen, la pregunta es doble:

  • ¿El lado del servidor TIME_WAITrealmente no hace nada y simplemente se deja así porque así RFClo requiere?
  • ¿La razón por la que se recomienda que el cliente inicie close() es porque el servidor TIME_WAITes inútil?

Respuesta1

Entcptérminos del lado del servidor aquí significa el host que tiene el socket en estado ESCUCHA.

RFC1122permite que el socket en estado TIME-WAIT acepte una nueva conexión con algunas condiciones

        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 obtener detalles exactos sobre las condiciones, consulte elRFC1122. Supongo que también debe haber un OPEN pasivo coincidente en el zócalo (zócalo en estado ESCUCHA).

Active OPEN (llamada de conexión del lado del cliente) no tiene tal excepción y debe dar un error cuando el socket está en TIME-WAIT, segúnRFC793.

Mi conjetura para la recomendación sobre el cierre iniciado por el cliente (en términos de TCP, el host que realiza OPEN activo, es decir, conexión) es muy similar a la suya, que en el caso común distribuye los sockets TIME-WAIT en más hosts donde hay abundancia de recursos para los enchufes. En el caso común, los clientes no envían SYN que reutilizaría los sockets TIME-WAIT en el servidor. Estoy de acuerdo en que aplicar dicha recomendación aún depende del caso de uso.

Respuesta2

El cliente utilizará un nuevo TCP ISN (número de secuencia inicial) basado en un algoritmo (incrementado en 1 aproximadamente cada 4 microsegundos), y el ISN básicamente siempre es mayor que el número de secuencia enviado en el último socket TCP "ip:par de puertos". FIN, por lo que el servidor siempre aceptará el nuevo SYN incluso si el "par ip:puerto" todavía está registrado en el estado TIME_WAIT en el servidor.

   RFC 793 [RFC0793] suggests that the choice of the ISN of a connection
   is not arbitrary, but aims to reduce the chances of a stale segment
   from being accepted by a new incarnation of a previous connection.
   RFC 793 [RFC0793] suggests the use of a global 32-bit ISN generator
   that is incremented by 1 roughly every 4 microseconds.

Respuesta3

Estees probablemente el ejemplo más claro de lo que realmente hace TIME-WAIT y, más importante aún, por qué es importante. También explica por qué evitar algunos de los consejos de los "expertos" en máquinas Linux para "reducir" el TIEMPO DE ESPERA.

Respuesta4

Con un protocolo no confiable, nunca puede estar seguro de haber recibido el último mensaje de su dispositivo par, por lo que es peligroso asumir que su par ha colgado el teléfono de repente. Una de las principales desventajas del protocolo TCP es que sólo se pueden abrir aproximadamente 65.000 puertos simultáneamente. Pero la forma de superar esto sería pasar a una granja de servidores, que escala mejor con la carga, que reciclar los números de puerto rápidamente. En el lado del cliente, es muy poco probable que se quede sin puertos si se trata de una estación de trabajo básica.

información relacionada