Vous êtes ici : Accueil > Produits > Network Monitor (Pro) > Manuel > Utiliser les sockets KEEPALIVE pour éviter les erreurs 10054

Utiliser les sockets KEEPALIVE pour éviter les erreurs 10054

par Vasiliy Ovchinnikov

Introduction

Dans les systèmes qui s'appuient sur des bases InterBase ou Firebird, conçus pour fonctionner en temps réel ou en quasi-temps réel, il est difficile de suivre l'état des connexions clientes côté serveur, et de les couper de force lorsque le client devient inaccessible après une rupture de liaison.

Il est important de libérer rapidement les ressources occupées par ces connexions fantômes, surtout avec des serveurs d'architecture Classic. Si des utilisateurs se connectent par une liaison modem instable, le risque de coupure est élevé.

Par exemple, un client enregistre un jeu d'enregistrements modifié, et la liaison se coupe après l'UPDATE, avant le COMMIT.

En règle générale, les applications clientes se reconnectent alors au serveur. Mais le client, qui continue de travailler sur des données dont l'enregistrement a échoué à cause de la coupure, ne pourra pas enregistrer ses modifications : il recevra un conflit de verrou (« lock conflict on update »). La connexion précédente, qui a ouvert la transaction (dans laquelle l'UPDATE a été exécuté, mais pas le COMMIT), détient encore ces enregistrements.

Des coupures peuvent aussi se produire sur un réseau local, si le matériel (cartes réseau, concentrateurs, commutateurs) est défaillant ou mal adapté, ou à cause d'un encombrement du réseau. Dans les journaux InterBase et Firebird, les échecs de connexions TCP apparaissent comme l'erreur 10054 sous Windows et 104 sous Unix ; les échecs NetBEUI apparaissent comme les erreurs 108/109.

Méthodes de contrôle des connexions bloquées

Dans InterBase et Firebird, le suivi et la coupure de ces connexions « mortes » reposent sur les paquets DUMMY ou sur les sockets KEEPALIVE.

À partir d'InterBase 5.0, le mécanisme des paquets DUMMY est implémenté au niveau applicatif, entre un serveur InterBase/Firebird et une bibliothèque cliente gds32/fbclient. Il se règle dans ibconfig/firebird.conf et n'est pas traité dans cet article.

Remarque

L'expérience montre que la stabilité du mécanisme de paquets dummy (celui d'InterBase 5.0, corrigé à plusieurs reprises dans Firebird 1.5.x) dépend fortement des systèmes d'exploitation du serveur et du client, des versions de la pile TCP et de bien d'autres conditions. Dans un réseau réel, l'efficacité de ce dispositif tend vers zéro.

Les sockets KEEPALIVE sont un mécanisme plus intéressant. Introduit dans InterBase 6.0 et versions suivantes, il sert à détecter les ruptures de connexion. KEEPALIVE s'active en positionnant l'option de socket SO_KEEPALIVE à l'ouverture. Il n'est pas nécessaire de le faire manuellement avec Firebird 1.5 ou supérieur : c'est déjà dans le code du serveur Firebird, pour Classic comme pour Superserver.

Pour les versions d'InterBase et de Firebird antérieures à 1.5, en architecture Classic, un réglage supplémentaire est nécessaire. Il est décrit ci-dessous.

Dans ce cas, c'est la pile TCP du système d'exploitation, et non le serveur Firebird, qui suit l'état de la connexion. Pour activer ce mécanisme, il faut toutefois ajuster les paramètres KEEPALIVE.

Description de KEEPALIVE

Le comportement des sockets KEEPALIVE est régi par les paramètres du tableau suivant.

Paramètre Description
KEEPALIVE_TIME Délai au bout duquel les sondes KEEPALIVE commencent
KEEPALIVE_INTERVAL Intervalle entre les sondes KEEPALIVE
KEEPALIVE_PROBES Nombre de sondes KEEPALIVE

La pile TCP détecte l'arrêt des échanges de paquets entre le client et le serveur en lançant le temporisateur KEEPALIVE. Dès que ce temporisateur atteint KEEPALIVE_TIME, la pile TCP du serveur envoie la première sonde KEEPALIVE. Une sonde est un paquet vide, avec l'indicateur ACK, envoyé au client. Si tout va bien côté client, sa pile TCP répond par un paquet ACK, et la pile du serveur réinitialise le temporisateur KEEPALIVE dès qu'elle reçoit la réponse.

Si le client ne répond pas à la sonde, le serveur continue d'en envoyer. Leur nombre est égal à KEEPALIVE_PROBES ; elles sont espacées de KEEPALIVE_INTERVAL. Si le client ne répond pas à la dernière sonde, la pile TCP du système ferme la connexion après un nouvel intervalle KEEPALIVE_INTERVAL, et le serveur (ici, une instance InterBase ou Firebird) libère toutes les ressources occupées par cette connexion.

Ainsi, une connexion cliente en échec est fermée au bout de l'intervalle suivant :

KEEPALIVE_TIME+ ( KEEPALIVE_PROBES+1)* KEEPALIVE_INTERVAL.

Par défaut, ces valeurs sont assez élevées, ce qui les rend peu utiles. Par exemple, KEEPALIVE_TIME vaut « 2 heures » sous Linux comme sous Windows. En pratique, 1 à 2 minutes suffisent pour décider de couper un client inaccessible. À l'inverse, les réglages par défaut de KEEPALIVE provoquent parfois des coupures forcées sur des réseaux Windows restés inactifs pendant ces 2 heures (on peut discuter de l'utilité de telles connexions dans les applications, mais c'est un autre sujet).

Le réglage de ces paramètres sous Windows et Linux est décrit ci-dessous.

Réglage de KEEPALIVE sous Linux

Sous Linux, les paramètres KEEPALIVE se modifient soit en éditant directement /proc, soit en appelant sysctl.

Dans le premier cas, modifiez les fichiers suivants :

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

Dans le second cas, exécutez les commandes suivantes :

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

La durée s'exprime en secondes.

Pour que ces paramètres soient repris au redémarrage du serveur, ajoutez les lignes suivantes :

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

Remplacez le mot <value> par les valeurs voulues.

Si vous utilisez Firebird Classic dans une version antérieure à 1.5, ajoutez la ligne suivante dans /etc/xinet.d/firebird :

FLAGS=REUSE KEEPALIVE

Réglage de KEEPALIVE sous Windows 95/98/ME

Branche du registre :

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP

Tout sur le réglage de TCP se trouve ici :

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

Paramètres :

  • KeepAliveTime = millisecondes
    Type : DWORD
    Sous Windows 98, type STRING.
    Définit la durée d'inactivité de la connexion, en millisecondes.
    À l'expiration, les sondes KEEPALIVE commencent.
    La valeur par défaut est de 2 heures (7200000).
  • KeepAliveInterval = valeur sur 32 bits
    Type : DWORD
    Sous Windows 98, type STRING.
    Définit l'intervalle entre les sondes KEEPALIVE (en millisecondes).
    Dès que l'intervalle KeepAliveTime indiqué est écoulé,
    après chaque intervalle KeepAliveInterval (en millisecondes),
    des sondes KEEPALIVE sont envoyées, jusqu'au nombre maximal
    MaxDataRetries. Sans réponse, la connexion
    est fermée. La valeur par défaut est de 1 seconde (1000).
  • MaxDataRetries = valeur sur 32 bits
    Type : STRING
    Définit le nombre maximal de sondes KEEPALIVE.
    La valeur par défaut est 5.

Réglage de KEEPALIVE sous Windows 2000/NT/XP

Branche du registre :

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

Tout sur le réglage de TCP :

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

Le paramètre MaxDataRetries est remplacé par TCPMaxDataRetransmissions.

Tous les autres paramètres portent les mêmes noms que sous Windows 9x.

Réglage de KEEPALIVE sous Windows (pour les clients)

Ce réglage est facultatif, mais il peut réduire le nombre de messages d'échec de connexion si les canaux sont peu fiables. Ajoutez, dans la branche du registre :

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

le paramètre DisableDHCPMediaSense=1. Sa description se trouve ici :

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

Exemple

Prenons le réglage de Firebird SQL Server 1.5.2 CS sous Linux.

  • Vérifiez que le mécanisme de paquets DUMMY est désactivé dans firebird.conf
    (le paramètre est commenté)
    .......
    #DummyPacketsInterval=0
    ......
  • Vérifiez que le fichier de configuration /etc/xinet.d/firebird existe.

    Nous avons tout laissé tel que l'installation l'avait enregistré. Rien à ajouter.

  • Modifiez les paramètres de la pile 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

  • Connectez-vous à n'importe quelle base du serveur depuis un client du réseau.

  • Contrôlez le trafic sur le serveur avec un filtre de paquets.

    Si les paramètres sont ceux de /proc/sys/net/tcp_keepalive_*, le serveur émet une sonde dans les 15 secondes après l'arrêt du trafic sur le canal. Si le client est « vivant », le serveur reçoit un paquet de réponse. Le contrôle se répète 15 secondes plus tard, et ainsi de suite.

  • Si un client est physiquement éteint (multiplexeur ou modem coupé de façon inattendue, tout est possible), le serveur ne reçoit pas de réponse et commence à envoyer des sondes toutes les 10 secondes. Si le client ne répond pas à la cinquième sonde, le processus serveur se termine 10 secondes plus tard et libère les ressources et les verrous. Si le client émet le moindre signal et répond au moins à la cinquième sonde (au pire), le serveur recommence à envoyer des sondes après un nouveau délai de 15 secondes. Et ainsi de suite.

Recommandations

Pour conclure, quelques conseils pour choisir les valeurs KEEPALIVE.

D'abord, déterminez la valeur nécessaire de KEEPALIVE_TIME. Plus elle est élevée, plus les sondes KEEPALIVE démarrent tard. Si le journal du serveur affiche en permanence des erreurs 10054/104 que vous devez supprimer à la main, augmentez KEEPALIVE_TIME.

Ensuite, KEEPALIVE_INTERVAL et KEEPALIVE_PROBES doivent correspondre au délai que vous acceptez avant de libérer une connexion déjà bloquée. Si vos utilisateurs passent par des canaux peu fiables, augmentez le nombre de sondes et l'intervalle, afin de leur laisser le temps de détecter la panne et de se reconnecter. Si les clients utilisent une liaison DSL, ou accèdent au serveur SQL par le réseau local, vous pouvez réduire l'intervalle entre les sondes KEEPALIVE.

Recommandations générales : si vous recevez, sans raison particulière, de nombreux messages d'erreur des clients au moment d'enregistrer, à cause d'un conflit de verrou (c'est-à-dire sans connexions concurrentes sur les mêmes données), il faut que le système réagisse plus vite à la libération des connexions bloquées. En pratique, KEEPALIVE_TIME peut être supérieur ou égal à 1 minute. Estimez vous-même la durée de la transaction la plus longue, afin de ne pas surcharger le trafic avec des contrôles KEEPALIVE de connexions qui fonctionnent normalement et ont lancé de longues transactions. KEEPALIVE_INTERVAL est supérieur ou égal à 10 secondes, et KEEPALIVE_PROBES supérieur ou égal à 5 contrôles. Lorsque de nombreux utilisateurs travaillent en même temps, des contrôles trop fréquents peuvent augmenter nettement le trafic réseau.

N'oubliez pas non plus que, si vos utilisateurs modifient activement des données communes, des erreurs de verrou se produiront même dans une situation optimale. Il faut alors un traitement correct de ces erreurs dans les applications clientes. L'application doit aussi pouvoir en limiter l'occurrence.

Exemples de configuration par défaut

Voici enfin d'autres exemples de configurations par défaut. Le temps d'indisponibilité est la durée pendant laquelle les utilisateurs ne peuvent pas mettre à jour des données déjà modifiées par la transaction ouverte par la connexion bloquée. Le temps total est le délai au bout duquel la connexion bloquée est fermée.

  • Les clients utilisent des connexions modem ; la plupart des transactions sont courtes ; l'indisponibilité est limitée à 3 minutes :

    KEEPALIVE_TIME 1 minute KEEPALIVE_PROBES 3 KEEPALIVE_INTERVAL 30 secondes TOTAL 3 minutes

  • Les clients utilisent le réseau local ; la plupart des transactions sont courtes ; l'indisponibilité est limitée à 2 minutes :

    KEEPALIVE_TIME 30 s KEEPALIVE_PROBES 5 KEEPALIVE_INTERVAL 10 s TOTAL 90 secondes

  • Les clients utilisent n'importe quelle connexion ; l'indisponibilité n'est pas limitée :

    KEEPALIVE_TIME 12 minutes KEEPALIVE_PROBES 7 KEEPALIVE_INTERVAL 15 s TOTAL 14 minutes

Nous espérons que ces exemples suffisent pour régler correctement le mécanisme KEEPALIVE de la pile TCP.

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

 

 

Liens associés :