Servidor TCP soquete com alta RTT e retransmissões

2

Eu tenho um servidor TCP construído com soquetes em Python. O aplicativo que estou construindo é sensível ao tempo, então a integridade dos dados é importante, portanto, precisamos do TCP. A largura de banda é muito baixa.

E há um cliente que solicita dados do servidor a cada 50 ms. O cliente obtém como resposta uma mensagem OK, caso o servidor não tenha os dados ou os dados reais necessários.

Sempre que o cliente faz uma solicitação ao servidor, ele envia um quadro de 5 bytes (sem incluir os 40 bytes extras que vêm do IP e do TCP). Por outro lado, o servidor responde com um quadro de 5 bytes (na maioria dos casos) ou um quadro de > 70 bytes (geralmente a cada segundo)

Em ambos os lados, os soquetes são ajustados assim:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # this line is excluded in client's case
sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 8192)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
sock.settimeout(0.5)

Tudo funciona bem na rede local (sem atraso), mas sempre que me conecto ao servidor pelo IP público (estou encaminhando a porta), ele fica muito lento. O atraso pode ir até 15 segundos (no momento em que acaba), o que é incrivelmente grande. Na maioria das vezes o RTT permanece em 200-210 ms. No WireShark eu posso ver que existem muitas retransmissões (espúrias) e ACup de dup.

O que posso fazer? Já desativei o algoritmo do Nagle, mas sem sucesso ainda.

    
por Robert Lucian Chiriac 21.08.2016 / 08:08

1 resposta

2

Eu dei uma boa olhada nos arquivos de captura fornecidos e aqui está minha análise. Em resumo, eu acredito que este é um problema com seu roteador , que parece ser um Technicolor dispositivo de algum tipo.

Captura do lado do cliente

  • Seu cliente está com problemas importantes tentando se conectar a vários sites. Os sites HTTPS (www.bing.com, wdcp.microsoft.com etc) não recebem resposta após o estágio Client Hello, resultando em retransmissões e tempo limite eventual do dispositivo. Outro conjunto de solicitações HTTP para um site hospedado pela Akamai (104.90.152.18) está resultando em um Tempo Limite de Solicitação 408.
  • Examinando especificamente o tráfego do cliente para o servidor, a grande maioria das sessões começa razoavelmente bem, mas depois encontra perda de pacotes, resultando em retransmissões do cliente e tempos limite. Por exemplo, examine o número do pacote 161 - 207. No pacote 161, o cliente envia um pacote de dados para o servidor, mas não obtém resposta, fazendo com que o cliente retransmita por cerca de 15 segundos antes que a conexão seja interrompida.

    A maioria dos fluxos TCP demonstra esse comportamento, de modo que podemos concluir que os pacotes de dados do cliente não estão atingindo o servidor OU a resposta do servidor não está atingindo o cliente.

  • Olhando para a latência, há um atraso significativo (e volátil) entre a resposta SYN e SYN / ACK do servidor, variando de 168ms a 770ms.

Captura do lado do servidor

  • Infelizmente, a captura do lado do servidor não captura os mesmos eventos que a captura do lado do cliente. Eu também não tenho certeza onde exatamente na rede isso foi capturado, pois inclui tráfego de cliente e servidor. Redirecionamentos ICMP também estão sendo enviados, o que indica roteamento sub-ótimo. Eu não acredito que isso esteja causando o problema.
  • Se você aplicar um filtro de exibição wireshark para tcp.stream eq 1 || tcp.stream eq 2 , poderá ver os dois lados da comunicação. Especificamente, cliente > Firewall e, em seguida, Firewall > Servidor (e vice-versa). Mais uma vez, tudo começa bem e, em seguida, ao redor do pacote 407 as coisas ficam interessantes.

    O pacote # 407 marca o momento em que o cliente envia uma nova quantidade de dados para o servidor. O roteador recebe isso e encaminha para o servidor. O servidor envia um pacote de Confirmação de volta (pacote # 410), bem como outro pequeno pacote de dados (# 411). O que não vemos, no entanto, é o roteador passando esses pacotes de volta para o cliente - essa é a melhor evidência que eu descobri sobre isso ser um problema de roteador.

Compare isso com uma das muitas trocas bem-sucedidas, um pouco mais avançadas no rastreio - pacote 394 a 406, por exemplo:

  1. (# 394) O cliente envia um pacote de dados para o IP público do servidor
  2. (# 396) O roteador recebe e encaminha para o IP local do servidor
  3. (# 397) O servidor envia uma confirmação de volta para o IP NAT do cliente
  4. (# 398) O servidor envia um pequeno pacote de dados de volta ao IP NAT do cliente
  5. (# 401) O roteador envia a confirmação de volta ao IP local do cliente
  6. (# 402) O roteador envia o pequeno pacote de dados de volta ao IP local do cliente
  7. (# 403) O cliente envia uma confirmação de volta ao IP público do servidor para confirmar que recebeu os dados que o servidor enviou
  8. (# 406) O roteador encaminha a confirmação para o IP local do servidor.

Quando as coisas falham, tudo pára após o estágio 4 - os dois pacotes enviados do servidor parecem ter sido descartados no roteador.

Considerações Finais

  • A maioria das suas conexões TCP, e não apenas o seu aplicativo Python, parece estar sofrendo de problemas de desempenho, conforme demonstrado pelos muitos problemas de conexão na captura do lado do cliente.
  • Há uma prova razoável em sua captura do lado do servidor de que os pacotes estão sendo bloqueados quando precisarem ser encaminhados pelo roteador.
  • Seus testes concluíram que não há problemas ao testar esse aplicativo localmente, quando o tráfego não precisa atravessar o roteador para encaminhamento de porta.
  • Infelizmente, eu não estou familiarizado com os roteadores Technicolor e a única coisa que eu poderia sugerir seria verificar se há alguma regra de firewall ou qualidade de serviço ativada no roteador que possa estar impactando o desempenho. Talvez se você puder testar com um roteador alternativo ou hospedar seu aplicativo em outra rede para ver se os problemas persistem.
por 21.08.2016 / 13:28