Estableciendo TIME_WAIT TCP

Estamos tratando de ajustar una aplicación que acepta mensajes a través de TCP y también utiliza TCP para algunos de sus mensajes internos. Durante la prueba de carga, notamos que el tiempo de respuesta se degrada significativamente (y luego se detiene por completo) a medida que se realizan más solicitudes simultáneas al sistema. Durante este tiempo, vemos una gran cantidad de conexiones TCP en estado TIME_WAIT y alguien sugirió reducir la variable de entorno TIME_WAIT de su valor predeterminado de 60 segundos a 30.

Por lo que entiendo , la configuración TIME_WAIT esencialmente establece el tiempo en que un recurso TCP está disponible para el sistema nuevamente después de que se cierra la conexión.

No soy un “chico de la red” y sé muy poco sobre estas cosas. Necesito mucho de lo que está en esa publicación vinculada, pero “embrutecerme” un poco.

  • Creo que entiendo por qué el valor de TIME_WAIT no se puede establecer en 0, pero ¿se puede establecer con seguridad en 5? ¿Qué hay de 10? ¿Qué determina una configuración “segura” para este valor?
  • ¿Por qué el valor predeterminado para este valor es 60? Supongo que la gente mucho más inteligente que yo tenía buenas razones para seleccionar esto como un incumplimiento razonable.
  • ¿Qué más debería saber sobre los posibles riesgos y beneficios de anular este valor?

Una conexión TCP es especificada por la tupla (IP de origen, puerto de origen, IP de destino, puerto de destino).

La razón por la que hay un estado TIME_WAIT después del cierre de la sesión es porque todavía puede haber paquetes en vivo en la red en su camino hacia usted (o desde usted, que pueden solicitar una respuesta de algún tipo). Si tuviera que volver a crear la misma tupla y apareciera uno de esos paquetes, sería tratado como un paquete válido para su conexión (y probablemente cause un error debido a la secuencia).

Por lo tanto, la hora TIME_WAIT generalmente se establece para duplicar la edad máxima de los paquetes. Este valor es la edad máxima a la que se les permitirá llegar a sus paquetes antes de que la red los descarte.

Eso garantiza que, antes de que se te permita crear una conexión con la misma tupla, todos los paquetes que pertenecen a las encarnaciones previas de esa tupla estarán muertos.

Eso generalmente dicta el valor mínimo que deberías usar. La máxima duración del paquete viene dictada por las propiedades de la red, un ejemplo es que los tiempos de vida de los satélites son más altos que los tiempos de vida de la LAN, ya que los paquetes tienen mucho más que recorrer.

Por lo general, solo el punto final que emite un ‘cierre activo’ debe pasar al estado TIME_WAIT. Entonces, si es posible, haga que sus clientes emitan el cierre activo que dejará el TIME_WAIT en el cliente y NO en el servidor.

Consulte aquí: http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html y http: //www.isi .edu / touch / pubs / infocomm99 / infocomm99-web / para más detalles (el último también explica por qué no siempre es posible debido al diseño del protocolo que no toma TIME_WAIT en consideración).

Pax tiene razón acerca de los motivos de TIME_WAIT y de por qué debe tener cuidado al reducir la configuración predeterminada.

Una mejor solución es variar los números de puerto utilizados para el extremo de origen de sus sockets. Una vez que hagas esto, no te importará el tiempo de espera para los sockets individuales.

Para los zócalos de escucha, puede usar SO_REUSEADDR para permitir que el zócalo de escucha se enlace a pesar de los zócalos TIME_WAIT que se encuentran alrededor.

En Windows, puede cambiarlo a través del registro :

 ; Set the TIME_WAIT delay to 30 seconds (0x1E) [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters] "TcpTimedWaitDelay"=dword:0000001E 

configurar el tcp_reuse es más útil que cambiar time_wait, siempre y cuando tenga el parámetro (núcleos 3.2 y superiores, desafortunadamente que descalifica todas las versiones de RHEL y XenServer).

Dejar caer el valor, especialmente para usuarios conectados a VPN, puede dar como resultado la recreación constante de túneles proxy en la conexión de salida. Con la configuración predeterminada de Netscaler (XenServer), que es inferior a la configuración predeterminada de Linux, Chrome a veces tendrá que volver a crear el túnel proxy hasta una docena de veces para recuperar una página web. Las aplicaciones que no se vuelven a intentar, como Maven y Eclipse P2, simplemente fallan.

El motivo original para el parámetro (evitar la duplicación) fue hecho redundante por un TCP RFC que especifica la inclusión de la marca de tiempo en todas las solicitudes TCP.

He estado probando una aplicación de servidor (en Linux) utilizando un progtwig de prueba con 20 hilos.

En 959,000 ciclos de conexión / cierre tuve 44,000 conexiones fallidas y muchos miles de tomas en TIME_WAIT.

Establecí SO_LINGER en 0 antes de la llamada de cierre y en las ejecuciones posteriores del progtwig de prueba no hubo fallas de conexión y menos de 20 sockets en TIME_WAIT.

TIME_WAIT podría no ser el culpable.

 int listen(int sockfd, int backlog); 

De acuerdo con Unix Network Programming Volume1, el backlog se define como la sum de la cola de conexión completa y la cola de conexión incompleta.

Digamos que el retraso es 5. Si tiene 3 conexiones completadas (estado ESTABLISHED) y 2 conexiones incompletas (estado SYN_RCVD), y hay otra solicitud de conexión con SYN. La stack TCP simplemente ignora el paquete SYN, sabiendo que será retransmitido en otro momento. Esto podría estar causando la degradación.

Al menos eso es lo que he estado leyendo. 😉