Le RGM n'appelle pas directement la méthode de SONDE, mais plutôt la méthode de Démarrage_détecteur pour démarrer le détecteur une fois une ressource démarrée sur un noeud. La méthode de démarrage_détecteur_xfnts démarre le détecteur de pannes sous le contrôle du gestionnaire de processus. La méthode d'arrêt_détecteur_xfnts arrête le détecteur de pannes.
Le détecteur de pannes SUNW.xfnts effectue les opérations suivantes :
Il surveille périodiquement la santé du démon du serveur xfs à l'aide d'utilitaires spécifiquement conçus pour vérifier des services simples basés sur le protocole TCP, tels que xfs.
Il assure le suivi des problèmes rencontrés par une application dans un délai donné (à l'aide des propriétés Nombre_nouvelles_tentatives et Intervalle_nouvelles_tentatives) et décide s'il convient de redémarrer le service de données ou de le basculer dans le cas d'un échec total de l'application. Les fonctions scds_fm_action() et scds_fm_sleep() fournissent une assistance intégrée à ce mécanisme de suivi et de décision.
Il met en oeuvre la décision de basculement ou de redémarrage à l'aide de la fonction scds_fm_action().
Il met à jour l'état des ressources et le met à la disposition des outils d'administration et interfaces utilisateur graphiques.
La méthode xfonts_probe met une boucle en oeuvre. Avant cela, xfonts_probe :
Récupère les ressources d'adresses réseau de la ressource xfnts de la manière suivante :
/* Obtention des adresses IP disponibles pour cette ressource */ if (scds_get_netaddr_list(scds_handle, &netaddr)) { scds_syslog(LOG_ERR, "No network address resource in resource group."); scds_close(&scds_handle); return (1); } /* Renvoi d'une erreur en l'absence de ressources réseau */ if (netaddr == NULL || netaddr->num_netaddrs == 0) { scds_syslog(LOG_ERR, "No network address resource in resource group."); return (1); }
Appelle scds_fm_sleep() et transmet la valeur de Intervalle_sonde_complet sous la forme du délai imparti. La sonde passe en mode de sommeil pendant le délai défini par l'Intervalle_sonde_complet entre les sondages.
timeout = scds_get_ext_probe_timeout(scds_handle); for (;;) { /* * Sommeil pendant une durée d'Intervalle_sonde_complet entre les * sondages successifs. */ (void) scds_fm_sleep(scds_handle, scds_get_rs_thorough_probe_interval(scds_handle));
La méthode xfnts_probe met la boucle en oeuvre de la manière suivante :
for (ip = 0; ip < netaddr->num_netaddrs; ip++) { /* * Obtention du nom d'hôte et du port sur lesquels * la santé a été surveillée. */ hostname = netaddr->netaddrs[ip].hostname; port = netaddr->netaddrs[ip].port_proto.port; /* * HA-XFS ne prend en charge qu'un seul port * et obtient la valeur du port depuis la * première entrée du tableau des ports. */ ht1 = gethrtime(); /* Latch probe start time */ scds_syslog(LOG_INFO, "Probing the service on port: %d.", port); probe_result = svc_probe(scds_handle, hostname, port, timeout); /* * Mise à jour de l'historique des sondages du service, * action si nécessaire. * Blocage du délai de fin du sondage. */ ht2 = gethrtime(); /* Conversion en millisecondes */ dt = (ulong_t)((ht2 - ht1) / 1e6); /* * Calcul de l'historique des pannes * et action si nécessaire */ (void) scds_fm_action(scds_handle, probe_result, (long)dt); } /* Chaque ressource réseau */ } /* Toujours continuer le sondage */
La fonction svc_probe() met la logique de sondage en oeuvre. La valeur retournée par svc_probe() est transmise à scds_fm_action() qui détermine s'il convient de redémarrer l'application, de basculer le groupe de ressources ou de ne rien faire.
La fonction svc_probe() établit une connexion de socket simple au port spécifié en appelant scds_fm_tcp_connect(). Si la connexion échoue, svc_probe() renvoie une valeur de 100 indiquant un échec total. Si la connexion s'établit, mais que la déconnexion échoue, svc_probe() renvoie une valeur de 50 indiquant un échec partiel. Si la connexion et la déconnexion réussissent, svc_probe() renvoie une valeur de 0, indiquant une réussite.
Le code de svc_probe() est le suivant :
int svc_probe(scds_handle_t scds_handle, char *hostname, int port, int timeout) { int rc; hrtime_t t1, t2; int sock; char testcmd[2048]; int time_used, time_remaining; time_t connect_timeout; /* * Sondage du service de données par le biais d'une connexion de socket au port */ * spécifié dans la propriété liste_port de l'hôte alimentant le service * de données XFS. Si le service XFS configuré pour écouter le port * spécifié répond à la connexion, le sondage est réussi. * Dans le cas contraire, nous attendons pendant une période définie * dans la propriété délai_sonde avant de conclure à l'échec du sondage. */ /* * Utilisez le pourcentage SVC_CONNECT_TIMEOUT_PCT du délai imparti * pour vous connecter au port */ connect_timeout = (SVC_CONNECT_TIMEOUT_PCT * timeout)/100; t1 = (hrtime_t)(gethrtime()/1E9); /* * la sonde établit une connexion au nom d'hôte et au port spécifiés. * La connexion reçoit 95% du délai_sonde effectif. */ rc = scds_fm_tcp_connect(scds_handle, &sock, hostname, port, connect_timeout); if (rc) { scds_syslog(LOG_ERR, "Failed to connect to port <%d> of resource <%s>.", port, scds_get_resource_name(scds_handle)); /*il s'agit d'un échec total */ return (SCDS_PROBE_COMPLETE_FAILURE); } t2 = (hrtime_t)(gethrtime()/1E9); /* * Calculez le temps réel requis pour la connexion. Il doit être inférieur * ou égal à délai_connexion, le temps alloué à la connexion. * Si la connexion utilise tout le délai qui lui est imparti, * la valeur restante de délai_sonde transmise à cette fonction * est utilisée comme délai imparti à la déconnexion. Sinon, le * temps restant de l'appel de connexion est ajouté au délai * de déconnexion. * */ time_used = (int)(t2 - t1); /* * Utilisez le temps restant (timeout - time_took_to_connect) pour la déconnexion */ time_remaining = timeout - (int)time_used; /* * Si tout le délai est écoulé, utilisez un délai imparti court à code permanent * pour essayer une nouvelle fois de provoquer la déconnexion. Ceci évite la fuite fd. */ if (time_remaining <= 0) { scds_syslog_debug(DBG_LEVEL_LOW, "svc_probe used entire timeout of " "%d seconds during connect operation and exceeded the " "timeout by %d seconds. Attempting disconnect with timeout" " %d ", connect_timeout, abs(time_used), SVC_DISCONNECT_TIMEOUT_SECONDS); time_remaining = SVC_DISCONNECT_TIMEOUT_SECONDS; } /* * Renvoi d'un échec partiel en cas d'échec à la déconnexion. * Motif : l'appel de connexion réussit, ce qui signifie que * l'application vit. Un échec à la déconnexion peut * être dû à une application bloquée ou à une lourde charge. * Dans ce dernier cas, ne déclarez pas que l'application * est morte en renvoyant un échec total. Au lieu de cela, déclarez * qu'il s'agit d'un échec partiel. Si cette situation perdure, l'appel * de déconnexion échoue une nouvelle fois et l'application est * redémarrée. */ rc = scds_fm_tcp_disconnect(scds_handle, sock, time_remaining); if (rc != SCHA_ERR_NOERR) { scds_syslog(LOG_ERR, "Failed to disconnect to port %d of resource %s.", port, scds_get_resource_name(scds_handle)); /* il s'agit d'un échec partiel */ return (SCDS_PROBE_COMPLETE_FAILURE/2); } t2 = (hrtime_t)(gethrtime()/1E9); time_used = (int)(t2 - t1); time_remaining = timeout - time_used; /* * S'il ne reste pas de temps, n'effectuez pas le test complet avec * fsinfo. Au lieu de cela, renvoyez SCDS_PROBE_COMPLETE_FAILURE/2 * Cette opération garantit que si le dépassement du délai * imparti persiste, le serveur sera redémarré. */ if (time_remaining <= 0) { scds_syslog(LOG_ERR, "Probe timed out."); return (SCDS_PROBE_COMPLETE_FAILURE/2); } /* * La connexion et la déconnexion au port ont réussi. * Exécutez la commande fsinfo pour effectuer un contrôle total de * la santé du serveur. * Redirigez stdout, sans quoi la sortie de fsinfo * se retrouve sur la console. */ (void) sprintf(testcmd, "/usr/openwin/bin/fsinfo -server %s:%d> /dev/null", hostname, port); scds_syslog_debug(DBG_LEVEL_HIGH, "Checking the server status with %s.", testcmd); if (scds_timerun(scds_handle, testcmd, time_remaining, SIGKILL, &rc) != SCHA_ERR_NOERR || rc != 0) { scds_syslog(LOG_ERR, "Failed to check server status with command <%s>", testcmd); return (SCDS_PROBE_COMPLETE_FAILURE/2); } return (0); }
Après avoir terminé, svc_probe() renvoie une valeur indiquant une réussite (0), un échec partiel (50) ou un échec total (100). La méthode xfnts_probe transmet cette valeur à scds_fm_action().
La méthode xfnts_probe appelle scds_fm_action() pour déterminer la mesure à prendre. La logique scds_fm_action() est la suivante :
Gérez un historique cumulé des pannes dans la valeur de la propriété Intervalle_nouvelles_tentatives.
Si les pannes cumulées atteignent 100 (échec total), redémarrez le service de données. Si Intervalle_nouvelles_tentatives est dépassé, réinitialisez l'historique.
Si le nombre de redémarrage dépasse la valeur de la propriété Nombre_nouvelles_tentatives, dans le délai spécifié par Intervalle_nouvelles_tentatives , basculez le service de données.
Par exemple, supposons que la sonde établisse une connexion au serveur xfs, mais ne puisse pas se déconnecter. Ceci indique que le serveur tourne mais qu'il peut être bloqué ou être provisoirement soumis à une forte charge. Un échec de la déconnexion renvoie une erreur partielle (50) à scds_fm_action(). Cette valeur se situe sous le seuil de redémarrage du service de données, mais la valeur est gérée dans l'historique des pannes.
Si, pendant le sondage suivant, le serveur n'arrive à nouveau pas à se déconnecter, une valeur 50 est ajoutée à l'historique des pannes géré par scds_fm_action(). La valeur cumulée des pannes est à présent de 100 . Par conséquent, scds_fm_action() redémarre le service de données.