¿Cómo se decidieron estas configuraciones predeterminadas de TCP de Linux?

13

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_timede 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 psqlsesió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.

Josh Kupershmidt
fuente
Alguna información relevante aquí ... tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html
Drav Sloan
Tenga en cuenta que puede cambiar la primera de tres por conexión en el código de cliente con las opciones de conector TCP_KEEPIDLE, TCP_KEEPCNTy TCP_KEEPINTVL.
wnoise
1
@wnoise en realidad desde Linux 2.6.37 también debería ser posible especificar la opción de socket TCP_USER_TIMEOUT, en lugar de configurar todo el net.ipv4.tcp_retries2sistema. Por supuesto, muchas aplicaciones (como PostgreSQL en mi ejemplo aquí) aún no son compatibles TCP_USER_TIMEOUT.
Josh Kupershmidt

Respuestas:

6

RFC 1122 especifica en la sección 4.2.3.6 que el período de mantenimiento no debe ser inferior a dos horas.

wnoise
fuente
1
Bien, gracias por desenterrar eso. Creo que eso responde principalmente a la pregunta de por qué el valor tcp_keepalive_timepredeterminado es 7200, aunque todavía estaría interesado en el precedente / explicación de las otras tres configuraciones relevantes.
Josh Kupershmidt
Eliminando Mi respuesta ya que esto responde la pregunta (al menos para uno de los valores)
coteyr
1
@coteyr Gracias de todos modos, agradezco el esfuerzo. IIRC hubo un comentario intrigante en su respuesta que sugiere que en los núcleos de Linux anteriores el valor predeterminado era 15 minutos. Me interesaría cómo / por qué eso cambió a 2 horas, o se estableció en 15 minutos en primer lugar.
Josh Kupershmidt