Está aquí: Inicio > Productos > Network Monitor (Pro) > Manual del usuario > Uso de sockets KEEPALIVE para evitar errores 10054

Uso de sockets KEEPALIVE para evitar errores 10054

por Vasiliy Ovchinnikov

Introducción

En sistemas con bases de datos InterBase o Firebird destinados a funcionar en modo de tiempo real o casi en tiempo real, existe el problema de rastrear en el servidor el estado de las conexiones de clientes y forzar la desconexión cuando el cliente deja de estar accesible por pérdida de conexión.

Es importante liberar con prontitud los recursos ocupados por esas conexiones fantasma, especialmente en servidores con arquitectura Classic. Si algunos usuarios se conectan al servidor mediante una conexión modem inestable, el riesgo de desconexión es bastante alto.

Por ejemplo, un cliente guarda un conjunto de registros modificado y, después de ejecutar UPDATE (sin que se haya hecho COMMIT), se pierde la conexión.

Por regla general, las aplicaciones cliente en esas situaciones se reconectan al servidor, pero el cliente (que sigue trabajando con los datos cuyo guardado provocó un mensaje de error por fallo de conexión) no podrá guardar los cambios, ya que recibirá un mensaje de conflicto de bloqueo («lock conflict on update»). La conexión anterior, que abrió la transacción (en cuyo contexto se ejecutó UPDATE sin COMMIT), sigue reteniendo esos registros.

Los fallos de conexión también pueden ocurrir en una red local si el hardware (tarjetas de red, hubs, conmutadores) está averiado o mal ajustado, o por interferencias en la red. En los logs de InterBase y Firebird, los fallos de conexiones TCP se muestran como error 10054 en Windows y 104 en Unix; los fallos NetBEUI aparecen como errores 108/109.

Métodos de control de conexiones colgadas

En InterBase y Firebird se usan los mecanismos de paquetes DUMMY o sockets KEEPALIVE para detectar y cerrar esas conexiones «muertas».

En InterBase 5.0 y versiones posteriores, el mecanismo de paquetes DUMMY está implementado en la capa de aplicación entre un servidor InterBase/Firebird y la biblioteca cliente gds32/fbclient. Se configura en ibconfig/firebird.conf y no se examina en este artículo.

Nota

Según la experiencia previa, la estabilidad del mecanismo de paquetes dummy (implementado en InterBase 5.0 y corregido repetidamente en Firebird 1.5.x) depende en gran medida de los sistemas operativos del servidor y del cliente, de las versiones de la pila TCP y de muchas otras condiciones. En la práctica, la eficacia de ese sistema en una red real tiende a cero.

Los sockets KEEPALIVE son un mecanismo más interesante. Implementado en InterBase 6.0 y versiones posteriores, sirve para detectar fallos de conexión. KEEPALIVE se habilita estableciendo la opción de socket SO_KEEPALIVE al abrir la conexión. No hace falta configurarla manualmente si usa Firebird 1.5 o superior, ya que está implementada en el código del servidor Firebird, tanto en Classic como en Superserver.

Para versiones de InterBase y Firebird anteriores a 1.5, en la variante con arquitectura Classic, es necesaria una configuración adicional. Se describe más abajo.

En este caso, la pila TCP del sistema operativo (y no el servidor Firebird) pasa a ser responsable del estado de la conexión. Sin embargo, para habilitar este mecanismo debe ajustar los parámetros KEEPALIVE.

Descripción de KEEPALIVE

El comportamiento de los sockets KEEPALIVE se controla mediante los parámetros de la tabla siguiente.

Parámetro Descripción
KEEPALIVE_TIME Intervalo de tiempo tras el cual comienzan las sondas KEEPALIVE
KEEPALIVE_INTERVAL Intervalo de tiempo entre sondas KEEPALIVE
KEEPALIVE_PROBES Número de sondas KEEPALIVE

La pila TCP detecta el momento en que dejan de transmitirse paquetes entre el cliente y el servidor, iniciando el temporizador KEEPALIVE. En cuanto el temporizador alcanza KEEPALIVE_TIME, la pila TCP del servidor ejecuta la primera sonda KEEPALIVE. Una sonda es un paquete vacío con flag ACK enviado al usuario. Si todo está correcto en el cliente, la pila TCP del cliente envía un paquete de respuesta con flag ACK y la pila TCP del servidor reinicia el temporizador KEEPALIVE al recibir la respuesta.

Si el cliente no responde a la sonda, el servidor sigue enviando sondas. Su cantidad equivale al valor KEEPALIVE_PROBES; se ejecutan en el intervalo KEEPALIVE_INTERVAL. Si el cliente no responde a la última sonda, tras otro KEEPALIVE_INTERVAL la pila TCP del sistema operativo cierra la conexión y el servidor (en este caso, la instancia de InterBase o Firebird) libera todos los recursos ocupados por esa conexión.

Por tanto, una conexión de cliente fallida se cerrará tras el siguiente intervalo:

KEEPALIVE_TIME+ ( KEEPALIVE_PROBES+1)* KEEPALIVE_INTERVAL.

De forma predeterminada, los valores de los parámetros son bastante altos, lo que hace ineficaz su uso. Por ejemplo, el valor predeterminado de KEEPALIVE_TIME es «2 horas», tanto en Linux como en Windows. En realidad, 1-2 minutos bastarían para decidir la desconexión forzada de un cliente inaccesible. Por otro lado, la configuración predeterminada de KEEPALIVE a veces provoca desconexiones forzadas en redes Windows que permanecen inactivas durante esas 2 horas (desde luego, puede cuestionarse la necesidad de tales conexiones en las aplicaciones, pero es otro tema).

A continuación se describe el ajuste de estos parámetros en los sistemas operativos Windows y Linux.

Configuración de KEEPALIVE en Linux

Los parámetros KEEPALIVE en Linux pueden cambiarse editando directamente el sistema de archivos /proc o mediante sysctl.

En el primer caso, deben editarse las siguientes líneas:

/proc/sys/net/ipv4/tcp_keepalive_time /proc/sys/net/ipv4/tcp_keepalive_intvl /proc/sys/net/ipv4/tcp_keepalive_probes

En el segundo caso, deben ejecutarse los siguientes comandos:

sysctl -w net.ipv4.tcp_keepalive_time=value sysctl -w net.ipv4.tcp_keepalive_intvl=value sysctl -w net.ipv4.tcp_keepalive_probes=value

Los valores de tiempo se expresan en segundos.

Para configurar automáticamente estos parámetros al reiniciar el servidor, agregue lo siguiente:

net.ipv4.tcp_keepalive_intvl = value net.ipv4.tcp_keepalive_time = value net.ipv4.tcp_keepalive_probes = value

Sustituya la palabra <value> por los valores necesarios.

Si usa una versión de Firebird Classic anterior a 1.5, en /etc/xinet.d/firebird debe agregarse lo siguiente:

FLAGS=REUSE KEEPALIVE

Ajuste de KEEPALIVE en Windows 95/98/ME

Rama del registro:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP

Todo sobre el ajuste de TCP puede encontrarlo aquí:

http://support.microsoft.com/default.aspx?scid=kb;en-us;158474

Parámetros:

  • KeepAliveTime = milliseconds
    Type: DWORD
    For Windows 98, type STRING.
    Define el tiempo de inactividad de la conexión en milisegundos.
    Al expirar, comienzan las sondas KEEPALIVE.
    Valor predeterminado: 2 horas (7200000).
  • KeepAliveInterval = 32-digit value
    Type: DWORD
    For Windows 98, STRING type.
    Define el intervalo entre sondas KEEPALIVE (en milisegundos).
    En cuanto expire el intervalo KeepAliveTime indicado,
    tras cada KeepAliveInterval (en milisegundos)
    se envían sondas KEEPALIVE hasta el número máximo
    de MaxDataRetries. Si no hay respuesta, la conexión
    se cierra. Valor predeterminado: 1 segundo (1000).
  • MaxDataRetries = 32-digit value
    Type: STRING
    Define el número máximo de sondas KEEPALIVE.
    Valor predeterminado: 5.

Configuración de KEEPALIVE en Windows 2000/NT/XP

Rama del registro:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\.

Todo sobre el ajuste de TCP:

XP: http://support.microsoft.com/kb/314053

El parámetro MaxDataRetries se sustituye por TCPMaxDataRetransmissions.

Todos los demás parámetros tienen los mismos nombres que en Windows 9x

Configuración de KEEPALIVE en Windows (para clientes)

Esta configuración es opcional, pero puede reducir la cantidad de mensajes sobre fallos de conexión si usa canales de comunicación poco fiables. Agregue en la rama del registro:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

el parámetro DisableDHCPMediaSense=1. Vea la descripción de este parámetro aquí:

https://support.microsoft.com/en-us/help/239924/how-to-disable-the-media-sensing-feature-for-tcp-ip-in-windows

Ejemplo

Consideremos el ajuste de Firebird SQL Server 1.5.2 CS bajo Linux.

  • Asegúrese de que el mecanismo de paquetes DUMMY esté deshabilitado en firebird.conf
    (el parámetro está comentado)
    .......
    #DummyPacketsInterval=0
    ......
  • Asegúrese de que existe el archivo de configuración /etc/xinet.d/firebird

    Dejamos todo sin cambios, como quedó registrado durante la instalación. No hace falta agregar nada.

  • Cambie los parámetros de la pila TCP:

    sysctl -w net.ipv4.tcp_keepalive_time = 15 sysctl -w net.ipv4.tcp_keepalive_intvl = 10 sysctl -w net.ipv4.tcp_keepalive_probes = 5

  • Conéctese a cualquier base de datos del servidor desde cualquier cliente de red

  • Compruebe el tráfico en el servidor con cualquier filtro de paquetes.

    Con los parámetros indicados en /proc/sys/net/tcp_keepalive_*, dentro de 15 segundos después de que todo se detenga en el canal, el servidor crea una sonda. Si el cliente está «activo», el servidor recibe un paquete de respuesta. 15 segundos después se repite la comprobación, y así sucesivamente.

  • Si un cliente se apaga físicamente (el multiplexor o el módem se desconecta inesperadamente — cualquier cosa es posible), el servidor no recibe respuesta y comienza a enviar sondas cada 10 segundos. Si el cliente no responde a la quinta sonda, 10 segundos después el proceso del servidor finaliza y libera recursos y bloqueos. Si el cliente envía señales y responde al menos a la quinta sonda (en el peor caso), tras otro timeout de 15 segundos el servidor volverá a enviar sondas. Y así sucesivamente.

Recomendaciones

Para concluir, le ofrecemos algunas recomendaciones sobre cómo seleccionar los valores KEEPALIVE.

Primero, determine el valor necesario de KEEPALIVE_TIME. Cuanto mayor sea el valor, más tarde comenzarán las sondas KEEPALIVE. Si ve constantemente errores 10054/104 en el log del servidor y debe eliminarlos manualmente, se recomienda aumentar KEEPALIVE_TIME.

En segundo lugar, los valores de KEEPALIVE_INTERVAL y KEEPALIVE_PROBES deben ajustarse a sus necesidades de liberación oportuna de conexiones ya colgadas. Si sus usuarios se conectan al servidor por canales poco fiables, probablemente quiera aumentar el número de sondas y el intervalo entre ellas, para dar al usuario oportunidad de detectar el fallo y reconectarse. Si los clientes usan DSL a Internet o acceden a un servidor SQL por la red local, puede reducir el intervalo entre sondas KEEPALIVE.

Recomendaciones generales: si sin motivo aparente recibe de los clientes muchos mensajes de error al guardar resultados por conflicto de bloqueo (es decir, no hay conexiones concurrentes trabajando con los mismos datos), debe aumentar la reacción del sistema ante la liberación de conexiones colgadas. En la práctica, KEEPALIVE_TIME puede ser de 1 minuto o más. Estime usted mismo el tiempo de la transacción más larga, para no sobrecargar el tráfico con comprobaciones KEEPALIVE de conexiones normales con transacciones largas. KEEPALIVE_INTERVAL debe ser de 10 segundos o más, y KEEPALIVE_PROBES de 5 comprobaciones o más. Con muchos usuarios simultáneos, recuerde que comprobar con demasiada frecuencia puede aumentar considerablemente el tráfico de red.

Recuerde también que si sus usuarios modifican activamente datos compartidos, los errores de bloqueo pueden ocurrir en condiciones normales. En ese caso necesita un manejo correcto de errores de bloqueo en las aplicaciones cliente. Al mismo tiempo, la aplicación debe minimizar la aparición de esos errores.

Ejemplos de configuración predeterminada

Por último, algunos ejemplos más de configuraciones predeterminadas. El tiempo de inactividad (downtime) es el período durante el cual los usuarios no podrán actualizar datos (que en ese momento fueron actualizados por la transacción abierta por la conexión colgada). El tiempo total es el intervalo tras el cual se cerrará la conexión colgada.

  • Los clientes usan conexiones modem; la mayoría de las transacciones son cortas; el tiempo de inactividad se limita a 3 minutos:

    KEEPALIVE_TIME 1 minutes KEEPALIVE_PROBES 3 KEEPALIVE_INTERVAL 30 seconds TOTAL 3 minutes

  • Los clientes usan conexión LAN; la mayoría de las transacciones son cortas; el tiempo de inactividad se limita a 2 minutos:

    KEEPALIVE_TIME 30 sec KEEPALIVE_PROBES 5 KEEPALIVE_INTERVAL 10 sec TOTAL 90 seconds

  • Los clientes usan cualquier tipo de conexión; el tiempo de inactividad no está regulado:

    KEEPALIVE_TIME12 minutes KEEPALIVE_PROBES 7 KEEPALIVE_INTERVAL 15 sec TOTAL 14 minutes

Esperamos que los ejemplos mostrados sean suficientes para ajustar correctamente el mecanismo KEEPALIVE de la pila TCP.

Fuente: https://www.ibphoenix.com/resources/documents/how_to/doc_104

 

 

Enlaces relacionados: