Ir al contenido principal

La captura del TCP Backlog es un efecto que evita que una aplicación de servidor en el módulo Stratus que escucha en el puerto X cree con éxito una conexión con cualquier cliente que intente conectarse al puerto X. Las conexiones a otros puertos, incluso de los mismos clientes, funcionan bien. La solución típica es apagar y reiniciar la aplicación del servidor. Este post explicará por qué la captura de atrasos ocurre y otras soluciones menos drásticas.

El atraso del TCP es la cola de las conexiones pendientes, es decir, las solicitudes de conexión que se han recibido pero que aún no han sido aceptadas. En las aplicaciones compiladas en versiones anteriores a OpenVOS 17.1 y en las aplicaciones compiladas en OpenVOS 17.1 pero sin las librerías POSIX, las peticiones de conexión no se envían un acuse de recibo hasta que son aceptadas por la aplicación. El cliente reenviará el paquete de solicitud de conexión entre 3 y 10 veces a intervalos crecientes. Los detalles exactos dependerán del sistema operativo del cliente y de cómo esté configurado. En algún momento la aplicación del servidor acepta la solicitud de conexión y la pila STCP envía un acuse de recibo. Siempre que ese acuse de recibo se reciba antes de que el cliente se dé por vencido, la conexión se completará y la comunicación podrá comenzar.

El escenario de captura de atrasos requiere varias condiciones

  1. Hay un fallo temporal de la red entre el servidor y el cliente (pero no entre el cliente y el servidor). Esto permite que las solicitudes de conexión del cliente sean recibidas por el servidor, pero impide que el cliente reciba los acuses de recibo de la conexión del servidor.
    o

    La aplicación del servidor retrasa la llamada a la función de aceptación por alguna razón.

  2. El cliente sigue enviando solicitudes de conexión; es decir, cuando la solicitud actual se agota, el cliente envía una nueva. El valor de tiempo de espera del cliente debe ser más corto que el valor de tiempo de espera del servidor.
  3. Un firewall con estado o algún otro dispositivo en algún lugar entre el cliente y el servidor temporiza las solicitudes de conexión del cliente y descarta los acuses de recibo de la conexión del servidor sin enviar una respuesta al servidor. Este valor de tiempo de espera debe ser más corto que el valor de tiempo de espera del servidor.

Lamentablemente, esta combinación de condiciones no es tan improbable como podría parecer a primera vista.

Normalmente comienza con una interrupción de la red que impide que los paquetes del servidor lleguen al cliente, pero permite que los paquetes del cliente lleguen al servidor. Cuando el paquete de solicitud de conexión del cliente llega al servidor se coloca en la cola de espera. Cuando la aplicación del servidor hace una llamada al código de aceptación, el código extrae la solicitud de conexión de la cola de espera y envía un acuse de recibo de la conexión. Como el servidor no recibe un acuse de recibo de su paquete, debido a que la red está rota, retransmite el acuse de recibo de la conexión. La pila TCP del cliente también retransmitirá la solicitud de conexión porque no ha recibido una confirmación. Después de un tiempo, la pila TCP del cliente se da por vencida y la aplicación cliente envía una nueva solicitud. El servidor sigue respondiendo a la primera solicitud. Después de alrededor de un minuto y medio (por defecto) el servidor se apaga y saca la siguiente solicitud de la cola de espera. El cliente mientras tanto ha reenviado la segunda solicitud y podría estar en la tercera. Estas peticiones también están en la cola de espera. Es posible que algún otro cliente pueda conseguir que una solicitud de conexión se coloque en la cola de espera, pero para que se complete con éxito el cliente necesitaría un tiempo de espera mayor que el tiempo de espera del servidor multiplicado por la posición de la solicitud de conexión en la cola de espera. Una vez que se corrige la interrupción de la red, el cortafuegos con estado perpetúa la interrupción dejando caer silenciosamente los reconocimientos de conexión para los que ya no tiene estado porque sólo mantiene el estado durante un tiempo menor que el tiempo de espera del servidor.

¿Cómo reconoces esto?

Primero el atraso está completo o al menos se está llenando. Puedes mostrar la cola de atrasos para una conexión con este comando.

analyze_system -request_line (string match backlog -o syncnt (byte 3Bx) dump_st +
cbq -full -lport 7654 -faddr 0x) -quit 
OpenVOS versión 17.0.2au, analyze_system versión 17.0.2au 
El proceso actual es 154, paso 91CC7100, Noah_Davids.CAC 
syncnt 6 
atraso 5 
listo 11:41:19

El valor del puerto es el número del puerto local, 7654 en este caso. El valor de dirección extranjera (faddr) de 0 limita la salida a sólo la toma LISTENING. Si el valor del atraso más 1 es igual al valor de sincronización, el atraso está lleno. Si la sincronización es mayor que 0 y sube, la cola de atrasos se llena. El tamaño de la cola de atrasos es establecido por la aplicación cuando llama a la función de escucha.

En segundo lugar, tienes que mirar un rastreo del protocolo de la red. El rastreo mostrará que la última solicitud de conexión no es reconocida mientras haya acuses de recibo de una solicitud de conexión anterior y esos acuses de recibo no obtengan ningún tipo de respuesta.

El rastro de la figura 1 muestra esto. Cada conexión está etiquetada con un índice de flujo y también con un código de colores. La primera solicitud de conexión del cliente está en la trama 1 en el momento 0. El acuse de recibo se envía en la trama 2 y luego se retransmite en la trama 3. La trama 4 es el cliente retransmitiendo la solicitud de conexión. Como STCP ya está enviando acuses de recibo de la conexión, la trama 4 dispara sólo un acuse de recibo TCP en la trama 5. Las tramas 6 y 7 son los reconocimientos de conexión retransmitidos. La trama 8 es una solicitud de conexión retransmitida por el cliente. La trama 9 es el reconocimiento TCP disparado por la solicitud de conexión retransmitida y la trama 10 es otro reconocimiento de conexión retransmitida. La trama 11 es otra solicitud de conexión del cliente pero para una nueva segunda conexión. Observe que no hay respuesta y el cuadro 12 muestra una solicitud de conexión retransmitida. El cuadro 13 muestra un acuse de recibo de la conexión pero sigue siendo para la primera conexión. El cuadro 14 es una retransmisión de la segunda solicitud de conexión. La trama 14 es otra retransmisión de la segunda solicitud de conexión. La trama 15 muestra una nueva, tercera solicitud de conexión del cliente y las tramas 16 y 17 son retransmisiones. La trama 18 es otra retransmisión del reconocimiento de la conexión a la primera conexión. La trama 19 es otra solicitud de conexión con las tramas 20 y 21 las retransmisiones y la trama 22 es la cuarta nueva solicitud de conexión. Finalmente en la trama 23 STCP renuncia a la primera solicitud de conexión y envía un reset seguido en la trama 24 de un acuse de recibo de conexión a la segunda solicitud de conexión con una retransmisión en la trama 25. En este punto creo que entiendes la idea.

El STCP tomó desde el cuadro 0 al cuadro 23 hasta el tiempo de espera, un total de 106,9 segundos. Mientras que el cliente no envía un reset cuando se agota el tiempo de espera, el tiempo entre el inicio de la segunda y la tercera solicitud de conexión (cuadro 11 a cuadro 15) es de 29,152 segundos y entre la tercera y la cuarta (cuadros 15 y 19) es de 25,8 segundos; mucho más rápido que STCP.

¿Qué puede hacer para prevenir esto?

La mejor solución es actualizar a OpenVOS 17.1 y recompilar la aplicación con las librerías POSIX. Haciendo esto evitará que el problema ocurra, ya que STCP enviará un reconocimiento de conexión inmediatamente, sin esperar a que la aplicación llame a aceptar. Sin embargo, puede cambiar otros comportamientos de su aplicación y se deben hacer pruebas cuidadosas de su aplicación. Si no es posible actualizar y recompilar, puede

  1. Reconfigurar el dispositivo de red con estado que está dejando caer los acuses de recibo de la conexión para responder con un reinicio. Cuando el STCP reciba el restablecimiento pasará a la siguiente solicitud de conexión en la cola de espera. El resultado es que las solicitudes de conexión agotadas por el dispositivo con estado se agotarán rápidamente de la cola. Cualquier otra confirmación de conexión será manejada por el cliente, que enviará su propio reinicio o lo reconocerá.
  2. Evita que el cliente haga peticiones de conexión hasta que se vacíe la cola del servidor.
  3. Cierra el conector de escucha de la aplicación del servidor y vuelve a abrirlo. Típicamente, la aplicación no está diseñada para hacer esto, así que tienes que detener y reiniciar la aplicación del servidor.
  4. Configurar el valor syn_rcvd_abort a algo que sea más corto que el valor de tiempo de espera del cliente. El valor se modifica con la solicitud analyze_system set_stcp_param
    analyze_system -request_line 'set_stcp_param syn_rcvd_abort 15' -quit
    OpenVOS versión 17.0.2au, analyze_system versión 17.0.2au 
    El proceso actual es 151, paso 91530AC0, Noah_Davids.CAC 
    Cambiando el tiempo de espera tcp SYN_RCVD (syn_rcvd_abort) de off a 15 
    listo 11:07:44

    En el ejemplo anterior, el tiempo de espera se establece en 15 segundos. Los valores válidos están entre 1 y 180 con un valor de 0, lo que significa que se utiliza el valor predeterminado (unos 100 segundos).

    Esto evitará que un solo cliente cree una gran acumulación en la cola de espera. Lo corto que debe ser el valor dependerá de que muchos clientes puedan estar accediendo al servidor al mismo tiempo. El problema con este enfoque es que afecta a todos los clientes y a todos los puertos del servidor, no se puede tener un valor para un conjunto de puertos y otro para otro conjunto de puertos. Además, un valor demasiado bajo podría hacer que algunas conexiones que pasan por enlaces de alta latencia fallen cuando podrían tener éxito si el temporizador fuera más largo. Elegir un valor óptimo es más arte que ciencia