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_time
de 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 psql
sessã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.
TCP_KEEPIDLE
, TCP_KEEPCNT
e TCP_KEEPINTVL
.
TCP_USER_TIMEOUT
, em vez de definir todo o net.ipv4.tcp_retries2
sistema. É claro que muitas aplicações (como PostgreSQL no meu exemplo aqui) ainda não suportam TCP_USER_TIMEOUT
.