Recuperação lenta em thin streams Thin streams fall back to RTO
ID da causa rt-thin · Responsável principal Desenvolvimento do servidor (Equipe de desenvolvimento) · Também envolvidos Infraestrutura de servidores (Equipe de infraestrutura), Desenvolvimento do cliente (Equipe de desenvolvimento)
Quando o jogo manda pacotes pequenos e espaçados, o RTO chega antes de se juntarem os “3 pacotes seguintes”. Com a mesma perda, a conexão fica parada por muito mais tempo do que em uma transferência grande.
Por quê Com intervalo de cerca de 100 ms entre pacotes, há poucos pacotes ainda sem ACK (in flight) → Efeito Juntar 3 ACKs duplicados leva mais de 300 ms, então o RTO (ping + 200 ms) dispara antes; com perdas seguidas, ele dobra a cada vez → Na tela Cada perda trava o jogo por cerca de 0,3 s; se até o reenvio se perde, trava perto de 1 segundo e depois vem o avanço rápido
Responsável principal Desenvolvimento do servidor (Equipe de desenvolvimento) · Também envolvidos Infraestrutura de servidores (Equipe de infraestrutura), Desenvolvimento do cliente (Equipe de desenvolvimento)
O que fazer (Equipe de desenvolvimento)
Servidor: ligar o TCP_NODELAY (com o Nagle ligado, o RACK fica sem pacotes seguintes para a detecção), mandar os pacotes em tempo real por UDP, com retransmissão própria. Cliente: ligar o TCP_NODELAY, mandar os pacotes em tempo real do mesmo jeito que o servidor (UDP).
O que fazer (Equipe de infraestrutura)
Usar RACK-TLP (padrão no Linux recente), usar tcp_thin_linear_timeouts para que RTOs seguidos não dobrem.
Números de referência
Com intervalo de 100 ms entre pacotes e ping de 60 ms, a retransmissão rápida leva cerca de 360 ms (até chegarem 3 pacotes seguintes e voltar a confirmação deles), e o RTO cerca de 260 ms. Com RACK, o reenvio acontece logo, por volta de 160 ms, quando volta a confirmação do pacote seguinte. Com intervalo acima de 200 ms entre pacotes, nem o RACK é mais rápido que o RTO.
No gráfico
Lacuna e depois tudo junto · Volume recebido por conexão, expirações de RTO
Onde olhar
Comparar os incrementos de TcpExtTCPTimeouts (expirações do RTO), TcpExtTCPFastRetrans (retransmissão rápida), TcpExtTCPLossProbes e TcpExtTCPLossProbeRecovery (TLP) no nstat, e ver rto e backoff das conexões do jogo com ss -ti. Verificar também os valores de net.ipv4.tcp_recovery, tcp_early_retrans e tcp_sack no servidor
Confirma se
Entre as retransmissões, há mais expirações de RTO que retransmissões rápidas, e é comum ver backoff maior que 0 (passando por RTO) nas conexões do jogo. Durante a parada, o volume recebido fica em 0 e, quando a conexão se recupera, tudo chega de uma vez
Descarta se
Transferências grandes do mesmo servidor também ficam paradas por muito tempo: problema de perda sem relação com o perfil da conexão. Concentrado em conexões sem SACK e timestamps: “Remoção de opções TCP por equipamento intermediário”
Como verificar
Ferramentas de infra (sem precisar do código do jogo)
Saiba mais
O Linux já teve uma opção para thin streams que retransmitia com 1 ACK duplicado (tcp_thin_dupack), mas ela foi removida em 2017, e hoje o RACK cumpre esse papel. Com o Nagle ligado (TCP_NODELAY desligado), enquanto espera a confirmação do pacote perdido a conexão também não envia pacotes novos; o RACK fica sem pacotes seguintes para a detecção, e é preciso esperar o RTO.
Fontes
Thin-streams and TCPLinux kernel Thin streams como os de jogos, que enviam de forma esparsa, não se dão bem com a retransmissão rápida e dependem de timeouts longos; o critério é ter menos de 4 pacotes ainda sem ACK (in flight)
RFC 8985: The RACK-TLP Loss Detection Algorithm for TCPIETF O RACK detecta a perda quando um pacote enviado depois foi entregue; a espera do TLP é 2·SRTT (com uma folga para o ACK atrasado quando só há um pacote sem confirmação)
include/net/tcp.hLinux kernel TCP_RTO_MIN de 200 ms, critério de thin stream (menos de 4 pacotes in flight) e 6 tentativas lineares
tcp: remove thin_dupack featureLinux kernel Remoção do thin_dupack em janeiro de 2017 (Linux 4.11), com a explicação de que o RACK cumpre esse papel
IP SysctlLinux kernel tcp_thin_linear_timeouts: em thin streams, deixa de dobrar o RTO por até 6 tentativas (desligado por padrão)
net/ipv4/proc.cLinux kernel Nomes dos contadores no nstat: TCPTimeouts, TCPFastRetrans, TCPLossProbes, TCPLossProbeRecovery
net/ipv4/tcp_timer.cLinux kernel TCPTimeouts aumenta quando o timer de retransmissão (RTO) expira
SNMP counterLinux kernel TcpExtTCPFastRetrans (retransmissões fora do estado Loss), TcpExtTCPLossProbes (TLPs enviados), TcpExtTCPLossProbeRecovery (perdas recuperadas por TLP)