2008-12-03 16 views
58

Estamos tratando de sintonizar una aplicación que acepte mensajes a través de TCP y que también use 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 TIME_WAIT de estado y alguien sugirió la reducción de la variable TIME_WAIT medio ambiente desde que es por defecto de 60 segundos a 30.Configuración TIME_WAIT TCP

De what I understand, el ajuste TIME_WAIT esencialmente establece el tiempo se pone a disposición un recurso TCP al sistema nuevamente después de que se cierra la conexión.

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

  • creo que entiendo por qué el valor TIME_WAIT no puede ajustarse a 0, pero puede que con seguridad se establece en 5? ¿Qué hay de 10? ¿Qué determina una configuración "segura" para este valor?
  • ¿Por qué el valor predeterminado 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?
+0

También no desea configurarlo demasiado alto: http://stackoverflow.com/questions/1803566/what-is-the-cost-of-many-time-wait-on-the-server- lado – Pacerier

Respuesta

85

Una conexión TCP está 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 de usted que puede 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 le 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 debe 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.

+0

¿Cómo puedo determinar la "edad máxima del paquete"? ¿Este conjunto es el sistema operativo, algo en la red o alguna configuración de software? BTW, el código que "genera" la mayoría de estas conexiones es una plataforma de terceros para la que no tenemos una fuente. ¡Gracias por la excelente respuesta! – Vinnie

+4

El verdadero nombre es la duración máxima del segmento, MSL. No estoy seguro de que pueda cambiar esto en Windows o incluso si lo hace, debe estar configurado en función de las características de la red. Windows lo establece en 120s, creo. Todos los parámetros TCP están en HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Services \ Tcpip \ Parameters. – paxdiablo

+0

'No estoy seguro de que pueda cambiar esto en Windows o incluso si lo hace, debe estar configurado en función de las características de la red. Windows lo establece en 120, creo. ☹ Definitivamente puede [cambiarlo en Linux] (http://serverfault.com/a/23529/14019) y 120 es * camino * demasiado largo. No he probado para confirmarlo, pero parece que tener un retraso tan largo hace que el enrutamiento P2P en la mayoría de los enrutadores sea innecesario. – Synetech

9

Pax es correcto acerca de los motivos de TIME_WAIT, y por qué debe tener cuidado con la reducción de 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 sockets de escucha, puede usar SO_REUSEADDR para permitir que el zócalo de escucha se vincule a pesar de los zócalos TIME_WAIT que están alrededor.

+10

Voy a votar mejor que cualquier respuesta que comience con la frase "Pax es correcto". :-) – paxdiablo

+3

Para máquinas muy activas con muchos miles de enchufes activos, es posible vincular todos los puertos efímeros en TIME_WAIT. Una vez que eso sucede, no puede abrir más conexiones hasta que algunos enchufes terminen esperando. Reducir la duración de TIME_WAIT puede ayudar mucho. Como mencionó Len Holgate, es mucho mejor hacer que el cliente inicie de cerca activo, si es posible, ya que eso evita por completo el servidor de los derechos de TIME_WAIT. –

+1

Los números de puerto de origen se modifican automáticamente de forma predeterminada, y eso no ayuda a los estados de TIME_WAIT en el servidor. La solución correcta es asegurar que el cliente cierre primero. – EJP

19

Normalmente, 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 obtener más información (la última también explica por qué no siempre es posible debido al diseño de protocolo que no toma en cuenta TIME_WAIT).

+2

Buen punto, el servidor aún tendrá que esperar el ACK de su FIN, pero eso debería tomar menos tiempo. También es una buena práctica que el iniciador cierre la sesión, ya que solo generalmente sabe cuándo ha finalizado. – paxdiablo

-1

TIME_WAIT podría no ser el culpable.

int listen(int sockfd, int backlog); 

De acuerdo a la programación Unix Red Volumen 1, la cartera se define como la suma de cola de conexión completa y cola de conexión incompleta.

Digamos que el backlog 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 pila 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. ;)

+0

Estoy bastante seguro de que el retraso es solo para conexiones que aún no han alcanzado ESTABLECIDO; una vez que tienen, se eliminan de la cola; solo bloquean más conexiones entrantes hasta que se complete el protocolo de enlace (SYN, SYN/ACK, ACK), básicamente una vez que el servidor regrese de accept(). – paxdiablo

+1

(-1) No, el registro de escucha es solo para conexiones que no están completamente establecidas; es decir, han llegado a la pila TCP/IP pero aún no han sido 'aceptados'. Si su backlog es demasiado pequeño, su servidor rechazará las conexiones si las conexiones llegan más rápido de lo que puede aceptarlas. –

+2

Un malentendido menor. "cola de conexión completa. Esta cola contiene una entrada para cada conexión para la que se completa el protocolo de enlace de tres vías. El socket está en el estado ESTABLISHED. Cada llamada para accept() elimina la entrada frontal de la cola". http://www.sean.de/Solaris/soltune.html – yogman

3

En Windows, can change que through the registry:

; Set the TIME_WAIT delay to 30 seconds (0x1E) 

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters] 
"TcpTimedWaitDelay"=dword:0000001E 
+5

configuración tcp_fin_timeout no afecta a time_wait - esta es una idea errónea común. Es por algo totalmente diferente (un tiempo de espera FIN, obviamente). Muchas guías y tal punto a este ajuste, pero están equivocados. Mira tcp.h y verás que está codificado (Linux). – mcauth

0

he sido pruebas de carga de una aplicación de servidor (en Linux) mediante el uso de un programa 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 programa de prueba no hubo fallas de conexión y menos de 20 sockets en TIME_WAIT.

+0

Y también corrió el riesgo de perder datos. Esta no es la solución correcta. SO_LINGER no es algo con lo que se deba pelear. La solución correcta es garantizar que el cliente cierre primero, generalmente mediante la agrupación de conexiones en el cliente y escribiendo el servidor para manejar múltiples solicitudes por conexión. Al igual que HTTP 1.1 en realidad. – EJP

+0

Debería haber sido más claro en mi respuesta. No estoy abogando por establecer el tiempo de demora en 0 simplemente señalando el problema que observé en Windows. En Linux, este problema no sucedió. Por lo tanto, depende del sistema y, probablemente, depende de qué configuraciones del sistema estén activas. –

+0

No depende del sistema. Restablecer un socket como este pierde todos los datos en vuelo. – EJP

1

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

Al soltar el valor, especialmente para usuarios conectados a VPN, puede tener 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.