Ejemplo: implementación de un asesor de dos puertos

En el ejemplo siguiente se muestra cómo implementar un asesor de dos puertos. En este ejemplo de asesor personalizado se muestra la capacidad de detectar anomalías de un puerto de un servidor basándose en su propio estado y en el estado de otro daemon del servidor que se ejecuta en otro puerto de la misma máquina servidor.

Por ejemplo, si el daemon HTTP del puerto 80 deja de responder, quizá prefiera también detener el tráfico de direccionamiento al daemon SSL en el puerto 443.

El asesor es más radical que los asesores estándar, porque considera cualquier servidor que no envía una respuesta que ha dejado de funcionar y lo marca como inactivo. Los asesores estándar consideran que los servidores que no responden son muy lentos. Este asesor marca un servidor como inactivo para los puertos HTTP y SSL basándose en la falta de respuesta por parte de cada puerto.

Para utilizar este asesor personalizado, el administrador inicia dos instancias del asesor: una en el puerto HTTP y otra en el puerto SSL. El asesor crea instancias de dos tablas hash globales estáticas, una para HTTP y otra para SSL. Cada asesor intenta comunicarse con el daemon de servidor y almacena los resultados de este suceso en la tabla hash. El valor que cada asesor devuelve a la clase de asesor base depende de la posibilidad de comunicarse con su propio daemon de servidor y la posibilidad del asesor asociado para comunicarse con el daemon.

Se utilizan los siguientes métodos personalizados.
Se detectan las siguientes condiciones de error:
Este ejemplo está grabado para enlazar los puertos 80 para HTTP y 443 para SSL, pero se puede adaptar a cualquier combinación de puertos:
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; 

//-------- 
// Definir el elemento de las tablas hash utilizadas en este asesor personalizado 

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

//-------- 
// constructor 

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

//-------- 
// comprobar si este elemento es actual o caducado 
  public boolean isCurrent(ADV_twop oThis) { 
    boolean bCurrent; 
    int iLifetimeMs = 3 * 1000 * oThis.getInterval();     // establecer duración 
                                                          // como 3 ciclos de asesor 
    Date dNow = new Date(); 
    Date dExpires = new Date(dTimestamp.getTime() + iLifetimeMs); 

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

//-------- 
// value accessor(s) 

 public int getLoadValue() { return iLoad; } 

//-------- 
// clonar (evita el daño entre hebras) 

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

} 

//-------- 
// definir el asesor personalizado

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; 

   //-------- 
   // definir tablas para contener información de historial específica de puerto 

   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"; 

   //-------- 
   // crear matriz de bytes con mensaje de saludo del cliente SSL 

   public static final byte[] abClientHello = { 
     (byte)0x80, (byte)0x1c, 
     (byte)0x01,                                // saludo del cliente 
     (byte)0x03, (byte)0x00,                    // versión SSL 
     (byte)0x00, (byte)0x03,                    // long. especif. cifrado (bytes) 
     (byte)0x00, (byte)0x00,                    // long. ID sesión (bytes) 
     (byte)0x00, (byte)0x10,                    // long. datos desafío (bytes) 
     (byte)0x00, (byte)0x00, (byte)0x03,        // especif. cifrado
     (byte)0x1A, (byte)0xFC, (byte)0xE5, (byte)Ox20,    // datos de desafío
     (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 }; 

  //-------- 
  // constructor 

  public ADV_twop() { 
    super(ADV_TWOP_NAME, VERSION, ADV_TWOP_DEF_ADV_ON_PORT,
          ADV_TWOP_DEF_INTERVAL, "",
          false);                         // false = Load Balancer temporiza la respuesta 
    setAdvisor ( this ); 
  } 

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

  public void ADV_AdvisorInitialize() { 
    return; } 

  //-------- 
  // rutinas de acceso PUT y GET sincronizadas para las tablas hash 
  
  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 - determinar carga HTTP basada en la respuesta del servidor 

  int getLoadHTTP(int iConnectTime, ADV_Thread caller) { 
    int iLoad = ADV_HOST_INACCESSIBLE; 
    int iRc = caller.send(ADV_HTTP_REQUEST_STRING);   // enviar mensaje de solicitud 
                                                    // al servidor 
    if (0 <= iRc) {                                 // ¿la solicitud ha devuelto una anomalía? 
      StringBuffer sbReceiveData = new StringBuffer("") // asignar un almacenamiento intermedio 
                                                        // para la respuesta 
      iRc = caller.receive(sbReceiveData);              // obtener respuesta del servidor 
      
      if (0 <= iRc) {                             // ¿la recepción ha devuelto una anomalía? 
        if (0 < sbReceiveData.length()) {         // ¿hay datos ahí? 
          iLoad = SUCCESS;                        // omitir los datos recuperados y 
                                                  // devolver código de resultado satisfactorio 
      } 
    } 
  } 
  return iLoad; 
} 


//-------- 
// getLoadSSL() - determinar carga SSL según la respuesta del servidor 

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); // Realizar una recepción. 
      socket.getInputStream().read();                // Si la recepción es satisfactoria,
                                                     // se devuelve la carga 0. No nos
                                                     // preocupa el contenido de los datos
                                                     // y la carga se calcula con 
                                                     // la hebra ADV_Thread. 
      iLoad = 0; 
  } catch (IOException e) {           // En caso de error, iLoad lo tomará como valor predeterminado. 
  } 
  return iLoad; 
} 


//-------- 
// getLoad - fusionar resultados de los métodos HTTP y SSL 

public int getLoad(int iConnectTime, ADV_Thread caller) { 
  int iLoadHTTP; 
  int iLoadSSL; 
  int iLoad; 
  int iRc; 
  
  String sCluster = caller.getCurrentClusterId();  // dirección actual de clúster 
  int iPort = getAdviseOnPort(); 
  String sServer = caller.getCurrentServerId(); 
  String sHashKey = sCluster = ":" + sServer;      // clave de tabla hash 

  if (ADV_TWOP_PORT_HTTP == iPort) {                // manejar un servidor HTTP 
    iLoadHTTP = getLoadHTTP(iConnectTime, caller);  // obtener la carga para HTTP 
    
    ADV_nte nteHTTP = newADV_nte(sCluster, iPort, sServer, iLoadHTTP); 
    putNte(htTwopHTTP, "HTTP", sHashKey, nteHTTP);     // guardar información 
                                                       // HTTP 
    ADV_nte nteSSL = getNte(htTwopSSL, "SSL", sHashKey);  // obtener información 
                                                          // SSL
      if (null != nteSSL) { 
        if (true == nteSSL.isCurrent(this)) {              // comprobar indicación horaria 
          if (ADV_HOST_INACCESSIBLE != nteSSL.getLoadValue()) {    // ¿está funcionando 
                                                                   // HTTP? 
            iLoad = iLoadHTTP; 
          } else {                      // SSL no funciona, marcar els servidor HTTP como inactivo 
            iLoad= ADV_HOST_INACCESSIBLE; 
          } 
        } else {                 // la información de SSL ha caducado, marcar el 
                                 // servidor HTTP como inactivo 
          iLoad = ADV_HOST_INACCESSIBLE; 
       } 
     } else {                   // no hay información de carga sobre SSL, notificar 
                                // resultados de getLoadHTTP() 
       iLoad = iLoadHTTP; 
     } 
   } 
   else if (ADV_TWOP_PORT_SSL == iPort) {             // manejar un servidor SSL 
     iLoadSSL = getLoadSSL(iConnectTime, caller);     // obtener carga para SSL 
  
     ADV_nte nteSSL = new ADV_nte(sCluster, iPort, sServer, iLoadSSL); 
     putNte(htTwopSSL, "SSL", sHashKey, nteSSL);      // guardar información de carga SSL 

     ADV_nte nteHTTP = getNte(htTwopHTTP, "SSL", sHashKey);   // obtener información 
                                                              // HTTP 
     if (null != nteHTTP) { 
       if (true == nteHTTP.isCurrent(this)) {                 // comprobar indicación horaria 
         if (ADV_HOST_INACCESSIBLE != nteHTTP.getLoadValue()) {   // ¿está funcionando 
                                                                  // HTTP? 
           iLoad = iLoadSSL; 
         } else {             // el servidor HTTP no funciona, marcar SSL como inactivo 
           iLoad = ADV_HOST_INACCESSIBLE; 
         } 
       } else {     // información caducada de HTTP, marcar SSL como inactivo 
         iLoad = ADV_HOST_INACCESSIBLE; 
       } 
     } else {                 // no hay información de carga sobre HTTP, notificar 
                              // resultados de getLoadSSL() 
       iLoad = iLoadSSL; 
     } 
   } 

 //-------- 
 // manejador de errores 

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

Terms and conditions for information centers | Feedback

Last updated: May 23, 2013 03:57 PM EDT
File name: rprf_advex2port.html