Pular para o conteúdo principal

A captura TCP Backlog é um efeito que impede que uma aplicação do servidor no módulo Stratus que escuta na porta X crie com sucesso uma conexão com qualquer cliente que tente se conectar à porta X. Conexões com outras portas, mesmo dos mesmos clientes, funcionam bem. A solução típica é desligar e reiniciar a aplicação do servidor. Este post explicará porque a captura de backlog acontece e outras soluções menos drásticas.

O backlog TCP é a fila de conexões pendentes, ou seja, pedidos de conexão que foram recebidos mas ainda não foram aceitos. Em aplicações compiladas em versões pré OpenVOS 17.1 e em aplicações compiladas em OpenVOS 17.1, mas sem as bibliotecas POSIX, os pedidos de conexão não recebem um reconhecimento até que sejam aceitos pela aplicação. O cliente reenviará o pacote de solicitação de conexão entre 3 e 10 vezes em intervalos crescentes. Os detalhes exatos dependerão do sistema operacional do cliente e de como ele está configurado. Em algum momento o aplicativo servidor aceita o pedido de conexão e o stack STCP envia um aviso de recebimento. Desde que essa confirmação seja recebida antes que o cliente desista, a conexão será completada e a comunicação poderá começar.

O cenário de captura de atrasos requer várias condições

  1. Há uma falha temporária na rede entre servidor e cliente (mas não entre cliente e servidor). Isto permite que as solicitações de conexão do cliente sejam recebidas pelo servidor, mas impede que as confirmações de conexão do servidor sejam recebidas pelo cliente.
    ou

    A aplicação do servidor retarda a chamada da função de aceitação por algum motivo.

  2. O cliente continua a enviar pedidos de conexão; isto é, quando o cliente envia um novo pedido. O valor do tempo limite do cliente deve ser menor do que o valor do tempo limite do servidor.
  3. Um firewall de estado ou algum outro dispositivo em algum lugar entre o cliente e o servidor exclui os pedidos de conexão do cliente e descarta os reconhecimentos de conexão do servidor sem enviar uma resposta de volta ao servidor. Este valor de timeout deve ser menor do que o valor de timeout do servidor.

Infelizmente, esta combinação de condições não é tão improvável quanto poderia parecer inicialmente.

Normalmente começa com uma queda na rede que impede que os pacotes do servidor cheguem ao cliente, mas permite que os pacotes do cliente cheguem ao servidor. Quando o pacote de solicitação de conexão do cliente chega ao servidor, ele é colocado na fila de backlog. Quando a aplicação do servidor faz uma chamada para o código de aceitação, o código puxa o pedido de conexão da fila de backlog e envia uma confirmação de conexão. Como o servidor não recebe uma confirmação para seu pacote, porque a rede está quebrada, ele retransmite a confirmação da conexão. A pilha TCP do cliente também retransmitirá o pedido de conexão porque não recebeu um reconhecimento. Depois de algum tempo, a pilha TCP do cliente desiste e a aplicação do cliente envia um novo pedido. O servidor continua a responder à primeira solicitação. Após cerca de um minuto e meio (por padrão), o servidor se desliga e retira a próxima solicitação da fila de atraso. Enquanto isso, o cliente se ressente da segunda solicitação e pode estar na terceira. Estas solicitações também estão na fila de atraso. É possível que algum outro cliente possa ter uma solicitação de conexão colocada na fila de backlog, mas para que ela seja concluída com sucesso, o cliente precisaria de um timeout maior que o timeout do servidor multiplicado pela posição da solicitação de conexão na fila de backlog. Uma vez corrigida a interrupção da rede, o firewall de estado perpetua a interrupção, deixando silenciosamente de reconhecer que a conexão não tem mais estado, pois só mantém o estado por um tempo menor do que o timeout do servidor.

Como você reconhece isto?

Primeiro o acúmulo está cheio ou pelo menos cheio. Você pode exibir a fila de backlog para uma conexão com este comando.

analyze_system -request_line (string match backlog -or syncnt (byte 3Bx) dump_st +
cbq -full -lport 7654 -faddr 0x) -quit 
OpenVOS Release 17.0.2au, analyse_system Release 17.0.2au 
O processo atual é 154, passo 91CC7100, Noah_Davids.CAC 
syncnt 6 
atraso 5 
pronto 11:41:19

O valor do porto é o número do porto local, 7654 neste caso. O valor do endereço estrangeiro (faddr) de 0 limita a saída apenas para o soquete LISTENING. Se o valor do backlog mais 1 for igual ao valor de sincronização, o backlog está cheio. Se o valor de sincronização for maior que 0 e a fila de espera estiver preenchendo. O tamanho da fila de atraso é definido pela aplicação quando ela chama a função de escuta.

Em segundo lugar, você precisa olhar para um traço de protocolo de rede. O rastreamento mostrará que o último pedido de conexão não é reconhecido enquanto houver reconhecimentos de conexão para um pedido de conexão anterior e esses reconhecimentos não estão recebendo nenhum tipo de resposta.

O traço na figura 1 mostra isso. Cada conexão é rotulada com um índice de fluxo e também codificada por cores. O primeiro pedido de conexão do cliente está no frame 1 no momento 0. O reconhecimento é enviado no frame 2 e depois retransmitido no frame 3. O quadro 4 é o cliente que retransmite o pedido de conexão. Como a STCP já está enviando confirmações de conexão, o quadro 4 aciona apenas uma confirmação TCP no quadro 5. Os quadros 6 e 7 são retransmitidos com o reconhecimento da conexão. O quadro 8 é um pedido de retransmissão de conexão do cliente. O quadro 9 é a confirmação TCP acionada pelo pedido de conexão retransmitida e o quadro 10 é outra confirmação de conexão retransmitida. O quadro 11 é outro pedido de conexão do cliente, mas para uma nova segunda conexão. Note que não há resposta e o quadro 12 mostra uma solicitação de conexão retransmitida. O quadro 13 mostra um reconhecimento de conexão, mas ainda é para a primeira conexão. O quadro 14 é uma retransmissão da segunda solicitação de conexão. O quadro 14 é outra retransmissão da segunda solicitação de conexão. O quadro 15 mostra uma nova, terceira solicitação de conexão do cliente e os quadros 16 e 17 são retransmissões. O quadro 18 é outra retransmissão do reconhecimento da conexão para a primeira conexão. O quadro 19 é mais uma solicitação de conexão com os quadros 20 e 21, as retransmissões e o quadro 22 é a quarta nova solicitação de conexão. Finalmente no quadro 23 STCP desiste do primeiro pedido de conexão e envia um reset seguido no quadro 24 com um reconhecimento de conexão para o segundo pedido de conexão com uma retransmissão no quadro 25. Neste momento, acho que você entendeu a idéia.

O STCP levou do quadro 0 para o quadro 23 até o tempo esgotado, um total de 106,9 segundos. Enquanto o cliente não envia um reset quando o tempo é expirado, o tempo entre o início do segundo e terceiro pedidos de conexão (quadro 11 ao quadro 15) é de 29,152 segundos e entre o terceiro e quarto (quadros 15 e 19) é de 25,8 segundos; muito mais rápido que o STCP.

O que você pode fazer para evitar isso?

A melhor solução é atualizar para o OpenVOS 17.1 e recompilar o aplicativo com as bibliotecas POSIX. Isto evitará que o problema ocorra, já que o STCP enviará imediatamente um reconhecimento de conexão, sem esperar que a aplicação seja aceita. No entanto, isso pode mudar outros comportamentos de sua aplicação e testes cuidadosos de sua aplicação devem ser feitos. Se a atualização e a recompilação não forem possíveis, você pode

  1. Reconfigurar o dispositivo de rede estatal que está deixando cair os reconhecimentos de conexão para responder com um reset. Quando o STCP receber o reset, ele passará para o próximo pedido de conexão na fila de backlog. O resultado é que as solicitações de conexão cronometradas pelo dispositivo estadual serão rapidamente drenadas da fila. Qualquer outro reconhecimento de conexão será tratado pelo cliente, que enviará seu próprio reset ou os reconhecerá.
  2. Impedir o cliente de fazer pedidos de conexão até que a fila de atraso do servidor seja esvaziada.
  3. Feche a tomada de escuta da aplicação do servidor e reabra-a. Normalmente, a aplicação não é projetada para fazer isso, então você tem que parar e reiniciar a aplicação do servidor.
  4. Configurar o valor syn_rcvd_abort para algo que seja menor do que o valor de timeout do cliente. O valor é alterado com o set_system request set_stcp_param de análise.
    analyze_system -request_line 'set_stcp_param syn_rcvd_abort 15' -quit
    OpenVOS Release 17.0.2au, analyse_system Release 17.0.2au 
    O processo atual é 151, ptep 91530AC0, Noah_Davids.CAC 
    Mudando o tempo limite tcp SYN_RCVD (syn_rcvd_abort) de desligado para 15 
    pronto 11:07:44

    No exemplo acima, o tempo limite está definido em 15 segundos. Os valores válidos estão entre 1 e 180 com um valor 0 significando usar o tempo limite padrão (cerca de 100 segundos).

    Isto impedirá que um único cliente crie um grande acúmulo na fila de atraso. O quão curto o valor deve ser dependerá de muitos clientes poderem estar acessando o servidor ao mesmo tempo. O problema com esta abordagem é que afeta todos os clientes e todas as portas do servidor, não se pode ter um valor para um conjunto de portas e outro para outro conjunto de portas. Além disso, um valor muito baixo pode fazer com que algumas conexões que passam por links de alta latência falhem quando poderiam ter sucesso se o temporizador fosse mais longo. Escolher um valor ótimo é mais arte do que ciência

© 2020 Stratus Technologies.