Como foram decididas essas configurações padrão do TCP do Linux?

13

Passei bastante tempo rastreando um problema na produção recentemente, em que um servidor de banco de dados que desaparecesse causava um travamento de até 2 horas (longa espera por uma poll()chamada na biblioteca do cliente libpq) para um cliente conectado. Indo para o problema, percebi que esses parâmetros do kernel deveriam ser ajustados para baixo para que as conexões TCP cortadas fossem notadas em tempo hábil:

net.ipv4.tcp_keepalive_time = 7200 net.ipv4.tcp_keepalive_probes = 9 net.ipv4.tcp_keepalive_intvl = 75 net.ipv4.tcp_retries2 = 15

Os quatro valores acima são de uma máquina Ubuntu 12.04 e parece que esses padrões permanecem inalterados em relação aos padrões atuais do kernel Linux .

Essas configurações parecem ser fortemente tendenciosas para manter aberta uma conexão existente e extremamente mesquinhas com os testes de manutenção de atividade. AIUI, o padrão tcp_keepalive_timede 2 horas significa que, quando estamos aguardando uma resposta para um host remoto, aguardamos pacientemente por 2 horas antes de iniciar um probe keepalive para verificar se nossa conexão ainda é válida. E então, se o host remoto não responder a uma análise de keepalive, tentamos novamente essas análises 9 vezes ( tcp_keepalive_probes), espaçadas em 75 segundos ( tcp_keepalive_intvl), portanto, são 11 minutos extras antes de decidirmos que a conexão está realmente morta.

Isso corresponde ao que vi no campo: por exemplo, se eu iniciar uma psqlsessão conectada a uma instância remota do PostgreSQL, com alguma consulta aguardando uma resposta, por exemplo,

SELECT pg_sleep(30);

e, em seguida, fazer com que o servidor remoto sofra uma morte horrível (por exemplo, reduza o tráfego para essa máquina), vejo minha sessão psql aguardando até 2 horas e 11 minutos antes de descobrir que sua conexão está morta. Como você pode imaginar, essas configurações padrão causam sérios problemas ao código com o qual conversamos com um banco de dados durante, por exemplo, um evento de failover de banco de dados. Abaixar esses botões ajudou muito! E vejo que não estou sozinho em recomendar que esses padrões sejam ajustados.

Então, minhas perguntas são:

  • Há quanto tempo os padrões são assim?
  • Qual foi a lógica original para tornar essas configurações TCP o padrão?
  • Alguma distribuição Linux altera esses valores padrão?

E qualquer outra história ou perspectiva sobre a justificativa para essas configurações seria apreciada.

Josh Kupershmidt
fonte
Algumas informações relevantes aqui ... tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html
Drav Sloan
Note que você pode mudar o primeiro de três por conexão no código do cliente com as opções de socket TCP_KEEPIDLE, TCP_KEEPCNTe TCP_KEEPINTVL.
Wnoise
1
@wnoise, na verdade, desde o Linux 2.6.37 , também deve ser possível especificar a opção de soquete TCP_USER_TIMEOUT, em vez de definir todo o net.ipv4.tcp_retries2sistema. É claro que muitas aplicações (como PostgreSQL no meu exemplo aqui) ainda não suportam TCP_USER_TIMEOUT.
Josh Kupershmidt 19/08/2015

Respostas:

6

RFC 1122 especifica na seção 4.2.3.6 que o período de manutenção não deve ser padronizado em menos de duas horas.

wnoise
fonte
1
Bom, obrigado por desenterrar isso. Eu acho que isso responde principalmente à pergunta de por que o tcp_keepalive_timepadrão é 7200, embora eu ainda esteja interessado no precedente / explicação para as outras três configurações relevantes.
Josh Kupershmidt
Removendo minha resposta como isso responde à pergunta (pelo menos para um dos valores)
coteyr
1
@coteyr Obrigado de qualquer maneira, agradeço o esforço. No IIRC, houve um comentário intrigante em sua resposta, sugerindo que nos kernels anteriores do Linux o padrão era 15 minutos. Eu estaria interessado em como / por que isso foi alterado para 2 horas ou definido para 15 minutos em primeiro lugar.
Josh Kupershmidt 19/08/2015