Os nós cliente e servidor são CentOS7.9/X86_64. Se as solicitações HTTP POST foram enviadas diretamente ao servidor, cerca de 0,2% dos casos podem atingir o tempo limite. Se as solicitações HTTP POST forem enviadas por meio de um proxy NGINX no nó cliente, cerca de 20% dos casos atingirão o tempo limite. Confirmei que apenas um nó de back-end tem esse problema. Todos os outros nós são 100% bem-sucedidos, mesmo com maior taxa de transferência.
Após o tcpdump nos nós do back-end e com a análise do Wireshark. para uma solicitação bem-sucedida, o pacote tcp é recebido normalmente. como abaixo:
Dessa forma, o receptor TCP envia ACK para cada carga tcp grande.
para uma solicitação com falha, o receptor tcp reconhece apenas o tamanho 1398 para cada pacote tcp. 1398 é a carga tcp mínima como o cabeçalho MSS menos TCP/IP. (1410 - 66 = 1398), conforme abaixo:
O remetente TCP envia a retransmissão TCP 8 vezes em 60 segundos, mas o receptor TCP nunca envia um ACK de volta. O servidor HTTP fechou a conexão por 60 segundos de tempo limite de leitura.
Parece que os pacotes foram perdidos na pilha TCP do kernel em vez de na rede, já que os pacotes foram capturados no nó do lado do servidor. E no nó cliente, observa-se com o tcpdump que o cliente recebeu cada ACK do servidor rapidamente.
Alguém pode ajudar com isso? desde já, obrigado.
Aqui está a causa raiz:
o lado do cliente (nginx) não envia um sinalizador PSH.
o lado do servidor aumenta o tamanho da janela TCP para receber mais bytes e não envia ACK de volta.
o cliente envia mais bytes.
o servidor recebe mais bytes e aumenta o tamanho da janela. mas não enviou sinalizador ACK.
após 100ms, o lado do cliente considera os pacotes perdidos e reenvia os pacotes.
o servidor envia 'Duplicate ACK' e continua aumentando o tamanho da janela pois recebeu mais bytes apesar dos bytes duplicados.
o servidor envia 'Duplicate ACK' e continua a aumentar o tamanho da janela, pois recebeu mais bytes, apesar dos bytes duplicados.d ambos morrem de fome.
A solução:
nginx não envia PSH nem abre a configuração.
configurar no lado do servidor para reduzir o tamanho máximo da janela tcp para 32k resolveu o problema.