Guide des développeurs pour les services de données Sun Cluster 3.1 10/03

Détecteur de pannes SUNW.xfnts

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 :

Boucle principale xfonts_probe

La méthode xfonts_probe met une boucle en oeuvre. Avant cela, xfonts_probe :

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.

Fonction svc_probe()

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().

Détermination de l'action du détecteur de pannes

La méthode xfnts_probe appelle scds_fm_action() pour déterminer la mesure à prendre. La logique scds_fm_action() est la suivante :

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.