Recuperación lenta en thin streams Thin streams fall back to RTO
ID de la causa rt-thin · Responsable principal Desarrollo de servidor (Equipo de desarrollo) · También Infraestructura de servidores (Equipo de infraestructura), Desarrollo de cliente (Equipo de desarrollo)
Cuando se envían paquetes pequeños y espaciados, como en un juego, el RTO llega antes de que se junten los “3 paquetes posteriores”. Ante la misma pérdida, la conexión se detiene mucho más tiempo que en una transferencia grande.
Por qué Con paquetes cada 100 ms más o menos, hay muy pocos paquetes todavía sin ACK (in-flight) → Efecto Juntar 3 ACK duplicados lleva más de 300 ms, así que antes salta el RTO (ping + 200 ms), que se duplica si hay pérdidas seguidas → En pantalla Cada pérdida provoca un congelamiento de unos 0.3 s; si se pierde también la retransmisión, congelamiento de casi 1 segundo seguido de cámara rápida
Responsable principal Desarrollo de servidor (Equipo de desarrollo) · También Infraestructura de servidores (Equipo de infraestructura), Desarrollo de cliente (Equipo de desarrollo)
Tareas (Equipo de desarrollo)
Servidor: activar TCP_NODELAY (con Nagle activado, RACK no tiene paquetes posteriores en los que basarse), mover los paquetes en tiempo real a una retransmisión propia sobre UDP. Cliente: activar TCP_NODELAY, enviar los paquetes en tiempo real con el mismo modelo que el servidor (UDP).
Tareas (Equipo de infraestructura)
Usar RACK-TLP (predeterminado en los Linux recientes), evitar con tcp_thin_linear_timeouts que los RTO seguidos se dupliquen.
Cifras de referencia
Con paquetes cada 100 ms y un ping de 60 ms, la retransmisión rápida llega a los 360 ms aproximadamente (hasta que llegan 3 paquetes posteriores y vuelve su confirmación), y el RTO, a los 260 ms. Con RACK, se reenvía en cuanto vuelve la confirmación del paquete siguiente, a los 160 ms aproximadamente. Si los paquetes van separados más de 200 ms, RACK tampoco es más rápido que el RTO.
En el gráfico
Hueco y luego ráfaga · Datos recibidos por conexión, expiraciones del RTO
Dónde mirar
Comparar los incrementos de TcpExtTCPTimeouts (expiraciones del RTO), TcpExtTCPFastRetrans (retransmisiones rápidas), TcpExtTCPLossProbes y TcpExtTCPLossProbeRecovery (TLP) en nstat, y mirar rto y backoff de las conexiones del juego con ss -ti. Comprobar también los valores de net.ipv4.tcp_recovery, tcp_early_retrans y tcp_sack del servidor
Se confirma si
Entre las retransmisiones, las expiraciones del RTO superan a las retransmisiones rápidas, y en las conexiones del juego se ve a menudo un backoff mayor que 0 (un RTO en curso). Mientras dura la pausa no se recibe nada, y al recuperarse llega todo de golpe
Se descarta si
Si las transferencias grandes del mismo servidor también se detienen igual de tiempo, es un problema de pérdida que no depende del tipo de conexión. Si se concentra en conexiones sin SACK ni marcas de tiempo, apunta a “Eliminación de opciones TCP en dispositivos intermedios”
Se verifica con
Con herramientas de infraestructura (no hace falta código del juego)
Para saber más
Linux tuvo en su día una opción para thin streams que retransmitía con un solo ACK duplicado (tcp_thin_dupack), pero se eliminó en 2017, y hoy RACK cumple esa función. Con Nagle activado (TCP_NODELAY desactivado), mientras se espera la confirmación del paquete perdido tampoco se envían paquetes nuevos, así que RACK no tiene paquetes posteriores en los que basarse y hay que esperar al RTO.
Fuentes
Thin-streams and TCPLinux kernel Los thin streams, que envían de forma espaciada como los juegos, no aprovechan bien la retransmisión rápida y dependen de timeouts largos; el criterio es tener menos de 4 paquetes todavía sin ACK (in-flight)
RFC 8985: The RACK-TLP Loss Detection Algorithm for TCPIETF RACK da un paquete por perdido cuando se ha entregado otro enviado después; la espera de TLP es 2·SRTT (si solo queda un paquete sin confirmar, se añade margen para el ACK retardado)
include/net/tcp.hLinux kernel TCP_RTO_MIN 200 ms, criterio de thin stream (menos de 4 paquetes in-flight) y 6 reintentos lineales
tcp: remove thin_dupack featureLinux kernel En enero de 2017 se eliminó thin_dupack (Linux 4.11), con la explicación de que RACK cumple esa función
IP SysctlLinux kernel tcp_thin_linear_timeouts: en thin streams, el RTO no se duplica durante un máximo de 6 expiraciones (desactivado por defecto)
net/ipv4/proc.cLinux kernel Nombres de contador que muestra nstat: TCPTimeouts, TCPFastRetrans, TCPLossProbes y TCPLossProbeRecovery
net/ipv4/tcp_timer.cLinux kernel TCPTimeouts sube cuando expira el temporizador de retransmisión (RTO)
SNMP counterLinux kernel TcpExtTCPFastRetrans (retransmisiones fuera del estado Loss), TcpExtTCPLossProbes (TLP enviados) y TcpExtTCPLossProbeRecovery (pérdidas recuperadas con TLP)