Pasé bastante tiempo rastreando un problema en producción recientemente, donde la desaparición de un servidor de base de datos causaría un bloqueo de hasta 2 horas (larga espera para una poll()
llamada en la biblioteca del cliente libpq) para un cliente conectado. Al profundizar en el problema, me di cuenta de que estos parámetros del kernel deberían ajustarse hacia abajo para que las conexiones TCP cortadas se noten de manera oportuna:
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_retries2 = 15
Los cuatro valores anteriores son de una máquina Ubuntu 12.04, y parece que estos valores predeterminados no cambian de los valores predeterminados actuales del kernel de Linux .
Estas configuraciones parecen estar muy sesgadas para mantener abierta una conexión existente, y ser extremadamente tacaño con sondas keepalive. AIUI, el valor predeterminado tcp_keepalive_time
de 2 horas significa que cuando esperamos una respuesta para un host remoto, esperaremos pacientemente durante 2 horas antes de iniciar una sonda keepalive para verificar que nuestra conexión aún sea válida. Y luego, si el host remoto no responde a una sonda keepalive, reintentamos esas sondas keepalive 9 veces ( tcp_keepalive_probes
), separadas 75 segundos ( tcp_keepalive_intvl
), por lo que quedan 11 minutos adicionales antes de que decidamos que la conexión está realmente muerta.
Esto coincide con lo que he visto en el campo: por ejemplo, si comienzo una psql
sesión conectada a una instancia remota de PostgreSQL, con alguna consulta esperando una respuesta, por ejemplo
SELECT pg_sleep(30);
y luego hacer que el servidor remoto muera de una muerte horrible (por ejemplo, deje caer el tráfico a esa máquina), veo mi sesión de psql esperando hasta 2 horas y 11 minutos antes de que descubra que su conexión está inactiva. Como puede imaginar, esta configuración predeterminada causa serios problemas para el código que tenemos hablando con una base de datos durante, por ejemplo, un evento de conmutación por error de la base de datos. ¡Girar estos botones hacia abajo ha ayudado mucho! Y veo que no estoy solo al recomendar que se ajusten estos valores predeterminados.
Entonces mis preguntas son:
- ¿Cuánto tiempo han sido los valores predeterminados de esta manera?
- ¿Cuál fue la razón original para hacer que esta configuración TCP sea la predeterminada?
- ¿Alguna distribución de Linux cambia estos valores predeterminados?
Y cualquier otra historia o perspectiva sobre la justificación de estos ajustes sería apreciada.
TCP_KEEPIDLE
, TCP_KEEPCNT
y TCP_KEEPINTVL
.
TCP_USER_TIMEOUT
, en lugar de configurar todo el net.ipv4.tcp_retries2
sistema. Por supuesto, muchas aplicaciones (como PostgreSQL en mi ejemplo aquí) aún no son compatibles TCP_USER_TIMEOUT
.