Keepalive se encarga de comprobar si una conexión se mantiene activa o no. Para ello lo que hace es calcular el tiempo que transcurre desde el último paquete de datos recibido, con lo que si pasan una serie de segundos (previamente establecidos), el servidor intentará reconectar con el otro equipo un número determinado de veces cada X segundos... La cuestión está en que aunque la desconexión es realizada por el servidor, este tarda mucho en realizarla por "culpa" de los valores por defecto que tiene establecidos; valores que en entornos ideales no dan problemas, pero que en otros en cambio son más perjudiciales que beneficiosos.
Los valores que se encargan de establecer el "tiempo de vida" son tcp_keepalive_time, tcp_keepalive_intvl, tcp_keepalive_probes. La combinación de esos tres valores son las que consiguen que tengamos un tiempo de desconexión determinado, pero es importante saber diferencias las funciones de cada uno de éstos, pues son completamente diferentes los unos de los otros:
- tcp_keepalive_time: Establece el tiempo necesario que tiene que pasar sin recibir paquetes desde el otro equipo para empezar a mandar paquetes "keep alive"; paquete que en caso de que el otro lado estuviese activo/online recibiría respuesta. El valor por defecto son 7200 segundos (2 horas).
- tcp_keepalive_intvl: El intervalo de tiempo entre cada envío de paquetes "keep alive"(independientemente de que la conexión esté " viva o muerta"). El valor por defecto son 75 segundos.
- tcp_keepalive_probes: Establece el número de paquetes "keep alive" sin respuesta necesarios para considerar que una conexión está "muerta". El valor por defecto son 9 intentos.
Teniendo en cuenta todos estos valores veríamos que el total de tiempo que tendría que transcurrir para considerar una conexión completamente muerta sería de: 2 horas + (75 segundos * 9 intentos /60 segundos) = 2 horas, 11 minutos y 25 segundos... En definitiva; mucho tiempo; demasiado en algunos casos.
Para modificar estos valores podemos hacerlo o bien directamente para la sesión actual (que al reiniciar el equipo volverían a tener sus valores originales) o a nivel de kernel en sysctl para hacer los cambios persistentes... Esto es debido a que estos valores están almacenados en ficheros separados con el mismo nombre dentro del directorio virtual /proc/sys/net/ipv4/, así que estaríamos hablando de valores que afectarían directamente al núcleo del sistema. Es importante saber que, si bien se está efectuando un cambio sobre parámetros ipv4; estos parámetros en concreto también afectan a ipv6, con lo que no estaríamos dejando ningún cabo suelto. Si deseásemos hacer que el tiempo sin recibir paquetes fuese de 10 minutos (600 segundos) y que tras dicho intervalo de tiempo hiciese un máximo de 10 intentos fallidos cada 60 segundos, tendríamos dos formas de hacerlo.
La primera y más rudimentaria sería modificando los ficheros correspondientes a mano para que únicamente fuesen válidos hasta el próximo reinicio; esto se haría mediante estos tres comandos:
- echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time
- echo 60 > /proc/sys/net/ipv4/tcp_keepalive_intvl
- echo 10 > /proc/sys/net/ipv4/tcp_keepalive_probes
La solución es perfectamente válida, pero la verdad es que es algo chapucera, ya que rara vez se aplican estos cambios de forma temporal; y menos cuando dicha temporalidad depende de evitar reiniciar el equipo... Es por ello que es mucho más eficiente aplicar los cambios de forma permanente introduciendo los parámetros en /etc/sysctl.conf.
- echo 'net.ipv4.tcp_keepalive_time = 600' >> /etc/sysctl.conf
- echo 'net.ipv4.tcp_keepalive_intvl = 60' >> /etc/sysctl.conf
- echo 'net.ipv4.tcp_keepalive_probes = 10' >> /etc/sysctl.conf
- sysctl -p
Con esto sí que tendríamos los cambios aplicados de forma permanente, haciendo que nuestras conexiones estuviesen mucho menos tiempo "muertas". Si quisiésemos añadir más flexibilidad a estas reglas o ser más restrictivos con estas conexiones, solamente habría que jugar con estos parámetros hasta conseguir el balance ideal.
Espero que os haya resultado útil.
Saludos.