[AIX HP-UX Linux Solaris Windows]

Exemple : Implémentation d'un conseiller à deux ports

L'exemple suivant montre comment implémenter un conseiller à deux ports. Cet exemple de conseiller personnalisé illustre la possibilité de détecter l'échec d'un port d'un serveur en fonction de son propre statut et du statut d'un autre démon de serveur exécuté sur un autre port du même serveur.

Par exemple, si le démon HTTP sur le port 80 ne répond plus, vous pouvez arrêter également le routage du trafic vers le démon SSL sur le port 443.

Ce conseiller est plus agressif que les conseillers standard, car il prend en compte tout serveur qui n'envoie pas de réponse après s'être arrêté et le marque comme arrêté. Les conseillers standard, eux, considèrent que le serveur est lent. Ce conseiller marque un serveur comme étant arrêté pour les ports HTTP et SSL lorsque les ports ne répondent pas.

Pour utiliser ce conseiller personnalisé, l'administrateur démarre deux instances du conseiller : une pour le port HTTP et une autre pour le port SSL. Le conseiller instancie deux tables de hachage globales statiques, une pour HTTP et une autre pour SSL. Chaque conseiller tente de communiquer avec le démon du serveur et stocke les résultats de cet événement dans sa table de hachage. La valeur renvoyée par chaque conseiller à la classe du conseiller de base dépend de la possibilité de communiquer avec son propre démon serveur et de la faculté du conseiller partenaire de communiquer avec son démon.

Les méthodes personnalisées suivantes sont utilisées.
Les conditions d'erreur suivantes sont détectées :
Cet exemple est créé pour associer les ports 80 pour HTTP et 443 pour SSL, mais il peut être personnalisé et accepte toute combinaison de ports.
package CustomAdvisors;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.Date;
import com.ibm.internet.lb.advisors.*;
import com.ibm.internet.lb.common.*; 
import com.ibm.internet.lb.manager.*; 
import com.ibm.internet.lb.server.SRV_ConfigServer; 

//-------- 
// Définit l'élément table des tables de hachage utilisées dans le conseiller personnalisé 

class ADV_nte implements Cloneable { 
  private String sCluster; 
  private int     iPort; 
  private String sServer; 
  private int     iLoad; 
  private Date    dTimestamp; 

//-------- 
// constructeur 

  public ADV_nte(String sClusterIn, int iPortIn, String sServerIn, 
                 int iLoadIn) { 
    sCluster = sClusterIn; 
    iPort = iPortIn; 
    sServer = sServerIn; 
    iLoad = iLoadIn; 
    dTimestamp = new Date(); 
  } 

//-------- 
// vérifie si l'élément est actuel ou s'il a expiré 
  public boolean isCurrent(ADV_twop oThis) { 
    boolean bCurrent; 
    int iLifetimeMs = 3 * 1000 * oThis.getInterval();     // définit la durée de vie qui 
                                                          // correspond à 3 cycle de conseiller 
    Date dNow = new Date(); 
    Date dExpires = new Date(dTimestamp.getTime() + iLifetimeMs); 

    if (dNow.after(dExpires)) { 
      bCurrent = false; 
    } else { 
      bCurrent = true; 
    } return bCurrent; 
  } 

//-------- 
// accesseur(s) à la valeur 

 public int getLoadValue() { return iLoad; } 

//-------- 
// clone (évite l'altération entre les unités d'exécution) 

 public synchronized Object Clone() { 
   try { 
     return super.clone(); 
   } catch (cloneNotSupportedException e) { 
     return null; 
    } 
  } 

} 

//-------- 
// définit le conseiller personnalisé

public class ADV_twop extends ADV_Base 
   implements ADV_MethodInterface, ADV_AdvisorVersionInterface { 
   static final int ADV_TWOP_PORT_HTTP = 80; 
   static final int ADV_TWOP_PORT_SSL = 443; 

   //-------- 
   // définit les tables qui doivent contenir les informations historiques du port 

   static HashTable htTwopHTTP = new Hashtable(); 
   static HashTable htTwopSSL = new Hashtable(); 
   static final String ADV_TWOP_NAME = "twop"; 
   static final int ADV_TWOP_DEF_ADV_ON_PORT = 80; 
   static final int ADV_TWOP_DEF_INTERVAL = 7; 
   static final String ADV_HTTP_REQUEST_STRING = 
      "HEAD / HTTP/1.0\r\nAccept: */*\r\nUser-Agent: " + 
      "IBM_LB_Custom_Advisor\r\n\r\n"; 

   //-------- 
   // crée une matrice d'octets avec le message HELLO du client SSL 

   public static final byte[] abClientHello = { 
     (byte)0x80, (byte)0x1c, 
     (byte)0x01,                                // HELLO du client 
     (byte)0x03, (byte)0x00,                    // version SSL 
     (byte)0x00, (byte)0x03,                    // long. spéc. chiffrement (octets) 
     (byte)0x00, (byte)0x00,                    // long. ID session (octets) 
     (byte)0x00, (byte)0x10,                    // long. données réponse (octets) 
     (byte)0x00, (byte)0x00, (byte)0x03,        // spéc. chiffrement
     (byte)0x1A, (byte)0xFC, (byte)0xE5, (byte)Ox20,    // données réponse
     (byte)0xFD, (byte)0x3A, (byte)0x3C, (byte)0x18, 
     (byte)0xAB, (byte)0x67, (byte)0xB0, (byte)0x52, 
     (byte)0xB1, (byte)0x1D, (byte)0x55, (byte)0x44, (byte)0x0D, (byte)0x0A }; 

  //-------- 
  // constructeur 

  public ADV_twop() { 
    super(ADV_TWOP_NAME, VERSION, ADV_TWOP_DEF_ADV_ON_PORT,
          ADV_TWOP_DEF_INTERVAL, "",
          false);    // false = load balancer times the response 
    setAdvisor ( this ); 
  } 

  //-------- 
  // ADV_AdvisorInitialize 

  public void ADV_AdvisorInitialize() { 
    return; } 

  //-------- 
  // routines d'accès PUT et GET synchronisées pour les tables de hachage 
  
  synchronized ADV_nte getNte(Hashtable ht, String sName, String sHashKey) { 
    ADV_nte nte = (ADV_nte)(ht.get(sHashKey)); 
    if (null != nte) { 
      nte = (ADV_nte)nte.clone(); 
    } 
    return nte;
  } 
 synchronized void putNte(Hashtable ht, String sName, String sHashKey, 
                          ADV_nte nte) { ht.put(sHashKey,nte); return; 
} 


  //-------- 
  // getLoadHTTP : détermine la charge HTTP dans la réponse du serveur 

  int getLoadHTTP(int iConnectTime, ADV_Thread caller) { 
    int iLoad = ADV_HOST_INACCESSIBLE; 
    int iRc = caller.send(ADV_HTTP_REQUEST_STRING);  // envoie un message de demande 
                                                    // au serveur 
    if (0 <= iRc) {           // la demande a-t-elle retourné un échec ? 
      StringBuffer sbReceiveData = new StringBuffer("")    // alloue une mémoire tampon 
                                                        // à la réponse 
      iRc = caller.receive(sbReceiveData);    // obtient la réponse du serveur 
      
      if (0 <= iRc) {             // la réception a-t-elle renvoyé une erreur ? 
        if (0 < sbReceiveData.length()) {         // les données existent-elles ? 
          iLoad = SUCCESS;                        // ignore les données extraites et 
                                                  // retourne le code de succès 
      } 
    } 
  } 
  return iLoad; 
} 


//-------- 
// getLoadSSL() : détermine la charge SSL en fonction de la réponse du serveur 

int getLoadSSL(int iConnectTime, ASV_Thread caller) { 
  int iLoad = ADV_HOST_INACCESSIBLE; 
  int iRc; 

  CMNByteArrayWrapper cbawClientHello = new CMNByteArrayWrapper( 
                                                  abClientHello); 
  Socket socket = caller.getSocket(); 
  
  try { 
      socket.getOutputStream().write(abClientHello); // Exécute une réception. 
      socket.getInputStream().read();                // Si la réception aboutit,
                                                     // retourne la charge 0. Le contenu des
                                                     // données n'a pas d'importance
                                                     // et la charge est calculée par l'unité
                                                     // d'xécution ADV_Thread. 
      iLoad = 0; 
  } catch (IOException e) {           // En cas d'erreur, iLoad l'utilise par défaut. 
  } 
  return iLoad; 
} 


//-------- 
// getLoad - fusionne le résultat des méthodes HTTP et SSL 

public int getLoad(int iConnectTime, ADV_Thread caller) { 
  int iLoadHTTP; 
  int iLoadSSL; 
  int iLoad; 
  int iRc; 
  
  String sCluster = caller.getCurrentClusterId();  // adresse actuelle du cluster 
  int iPort = getAdviseOnPort(); 
  String sServer = caller.getCurrentServerId(); 
  String sHashKey = sCluster = ":" + sServer;      // clé de table de hachage 

  if (ADV_TWOP_PORT_HTTP == iPort) {                // gère un serveur HTTP 
    ¨iLoadHTTP = getLoadHTTP(iConnectTime, caller);  // obtient la charge HTTP 
    
    ADV_nte nteHTTP = newADV_nte(sCluster, iPort, sServer, iLoadHTTP); 
    putNte(htTwopHTTP, "HTTP", sHashKey, nteHTTP);     // enregistre les informations de charge 
                                                       // HTTP 
    ADV_nte nteSSL = getNte(htTwopSSL, "SSL", sHashKey);  // obtient les informations 
                                                          // HTTP
      if (null != nteSSL) { 
        if (true == nteSSL.isCurrent(this)) {              // vérifie l'horodatage 
          if (ADV_HOST_INACCESSIBLE != nteSSL.getLoadValue()) {    // SSL 
                                                                   // fonctionne-t-il ? 
            iLoad = iLoadHTTP; 
          } else {                      // SSL ne fonctionne pas ; le serveur HTTP est marqué comme étant arrêté 
            iLoad= ADV_HOST_INACCESSIBLE; 
          } 
        } else {                 // les informations SSL ont expiré : le serveur HTTP 
                                 // est marqué comme étant arrêté 
          iLoad = ADV_HOST_INACCESSIBLE; 
       } 
     } else {                   // aucune information de charge sur SSL, signale 
                                // le résultat getLoadHTTP() 
       iLoad = iLoadHTTP; 
     } 
   } 
   else if (ADV_TWOP_PORT_SSL == iPort) {             // gère un serveur SSL 
     iLoadSSL = getLoadSSL(iConnectTime, caller);     // obtient la charge SSL 
  
     ADV_nte nteSSL = new ADV_nte(sCluster, iPort, sServer, iLoadSSL); 
     putNte(htTwopSSL, "SSL", sHashKey, nteSSL);      // enregistre les infos SSL. 

     ADV_nte nteHTTP = getNte(htTwopHTTP, "SSL", sHashKey);   // obtient les informations 
                                                              // HTTP 
     if (null != nteHTTP) { 
       if (true == nteHTTP.isCurrent(this)) {       // vérifie l'horodatage 
         if (ADV_HOST_INACCESSIBLE != nteHTTP.getLoadValue()) {  // HTTP 
                                                                  // fonctionne-t-il ? 
           iLoad = iLoadSSL; 
         } else {             // le serveur HTTP ne fonctionne pas ; le serveur SSL est marqué comme étant arrêté 
           iLoad = ADV_HOST_INACCESSIBLE; 
         } 
       } else {     // les informations HTTP ont expiré : SSL est marqué comme étant arrêté 
         iLoad = ADV_HOST_INACCESSIBLE; 
       } 
     } else {                 // aucune information de charge sur HTTP, signale 
                              // le résultat getLoadSSL() 
       iLoad = iLoadSSL; 
     } 
   } 

 //-------- 
 // gestionnaire des erreurs 

   else { 
     iLoad = ADV_HOST_INACCESSIBLE; 
   } 
   return iLoad; 
  } 
} 



Référence associée
Exemple de conseiller
Rubrique de référence Rubrique de référence    

Conditions d'utilisation | Commentaires

Dernière mise à jourDernière mise à jour : Jun 21, 2011 12:02:44 PM EDT
Nom du fichier : rprf_advex2port.html