Il seguente esempio mostra come implementare un advisor a due porte. Questo esempio di advisor personalizzato dimostra la possibilità di rilevare un errore per una porta di un server in base al suo stato e allo stato di un daemon del server differente in esecuzione su un'altra porta sulla stessa macchina server.
Ad esempio, se il daemon HTTP sulla porta 80 smette di rispondere, potrebbe essere necessario arrestare l'instradamento del traffico al daemon SSL sulla porta 443.
Questo advisor è più aggressivo degli advisor standard, in quanto considera qualsiasi server che non invia una risposta come non funzionante e pertanto lo contrassegna come inattivo. Gli advisor standard considerano molto lenti i server che non rispondono. Questo advisor contrassegna un server come inattivo sia per la porta HTTP che per la porta SSL nel caso non vi sia una risposta dalla prima porta.
Per utilizzare questo advisor personalizzato, l'amministratore avvia due istanze dell'advisor: una sulla porta HTTP e una sulla porta SSL. L'advisor istanzia quindi due tabelle hash globali statiche, una per HTTP e una per SSL. Ogni advisor prova a comunicare con il daemon del server e memorizza i risultati di questo evento nella propria tabella hash. Il valore che ogni advisor restituisce alla classe dell'advisor di base dipende sia dalla capacità di comunicare con il proprio daemon del server che dalla capacità dell'advisor partner di comunicare con il relativo daemon.
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; //-------- // Definire l'elemento di tabella per le tabelle hash utilizzate in questo advisor personalizzato class ADV_nte implements Cloneable { private String sCluster; private int iPort; private String sServer; private int iLoad; private Date dTimestamp; //-------- // costruttore public ADV_nte(String sClusterIn, int iPortIn, String sServerIn, int iLoadIn) { sCluster = sClusterIn; iPort = iPortIn; sServer = sServerIn; iLoad = iLoadIn; dTimestamp = new Date(); } //-------- // verificare se questo elemento è corrente o scaduto public boolean isCurrent(ADV_twop oThis) { boolean bCurrent; int iLifetimeMs = 3 * 1000 * oThis.getInterval(); // impostare la durata come // 3 cicli dell'advisor 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; } //-------- // clone (evita il danneggiamento tra thread) public synchronized Object Clone() { try { return super.clone(); } catch (cloneNotSupportedException e) { return null; } } } //-------- // definire l'advisor personalizzato 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; //-------- // definire le tabelle che conterranno le informazioni sulla cronologia delle porte 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"; //-------- // creare un'array di byte con il messaggio hello del client SSL public static final byte[] abClientHello = { (byte)0x80, (byte)0x1c, (byte)0x01, // hello client (byte)0x03, (byte)0x00, // versione SSL (byte)0x00, (byte)0x03, // lungh spec cifre (byte) (byte)0x00, (byte)0x00, // lungh ID sessione (byte) (byte)0x00, (byte)0x10, // lunghezza dati (byte) (byte)0x00, (byte)0x00, (byte)0x03, // spec cifra (byte)0x1A, (byte)0xFC, (byte)0xE5, (byte)Ox20, // dati (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 }; //-------- // costruttore public ADV_twop() { super(ADV_TWOP_NAME, VERSION, ADV_TWOP_DEF_ADV_ON_PORT, ADV_TWOP_DEF_INTERVAL, "", false); // false = load balancer imposta l'ora della risposta setAdvisor ( this ); } //-------- // ADV_AdvisorInitialize public void ADV_AdvisorInitialize() { return; } //-------- // routine di accesso PUT e GET sincronizzate per le tabelle 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 - determinare il carico HTTP in base alla risposta del server int getLoadHTTP(int iConnectTime, ADV_Thread caller) { int iLoad = ADV_HOST_INACCESSIBLE; int iRc = caller.send(ADV_HTTP_REQUEST_STRING); // inviare il messaggio di richiesta // al server if (0 <= iRc) { // la richiesta ha restituito un errore? StringBuffer sbReceiveData = new StringBuffer("") // assegnare un buffer // per la risposta iRc = caller.receive(sbReceiveData); // richiamare la risposta dal server if (0 <= iRc) { // la ricezione ha ricevuto un errore? if (0 < sbReceiveData.length()) { // i dati sono presenti? iLoad = SUCCESS; // ignorare i dati richiamati e // restituire un codice di riuscita } } } return iLoad; } //-------- // getLoadSSL() - determinare il carico SSL in base alla risposta del server 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); // Effettuare una ricezione. socket.getInputStream().read(); // Se la ricezione riesce, // viene restituito un carico pari 0. Non // si conosce il contenuto dei dati, // e il carico viene calcolato mediante // il thread ADV_Thread. iLoad = 0; } catch (IOException e) { // In seguito a un errore, iLoad utilizzerà il valore predefinito. } return iLoad; } //-------- // getLoad - unire i risultati dai metodi HTTP e SSL public int getLoad(int iConnectTime, ADV_Thread caller) { int iLoadHTTP; int iLoadSSL; int iLoad; int iRc; String sCluster = caller.getCurrentClusterId(); // indirizzo cluster corrente int iPort = getAdviseOnPort(); String sServer = caller.getCurrentServerId(); String sHashKey = sCluster = ":" + sServer; // chiave tabella hash if (ADV_TWOP_PORT_HTTP == iPort) { // gestire un server HTTP iLoadHTTP = getLoadHTTP(iConnectTime, caller); // richiamare il carico per HTTP ADV_nte nteHTTP = newADV_nte(sCluster, iPort, sServer, iLoadHTTP); putNte(htTwopHTTP, "HTTP", sHashKey, nteHTTP); // salvare le informazioni // sul carico HTTP ADV_nte nteSSL = getNte(htTwopSSL, "SSL", sHashKey); // richiamare le informazioni // SSL if (null != nteSSL) { if (true == nteSSL.isCurrent(this)) { // verificare il formato orario if (ADV_HOST_INACCESSIBLE != nteSSL.getLoadValue()) { // SSL // funziona? iLoad = iLoadHTTP; } else { // SSL non funziona, quindi il server HTTP viene // contrassegnato come inattivo iLoad= ADV_HOST_INACCESSIBLE; } } else { // le informazioni SSL sono scadute, pertanto il server // HTTP viene contrassegnato come inattivo iLoad = ADV_HOST_INACCESSIBLE; } } else { // nessuna informazioni di carico su SSL, riportare // i risultati getLoadHTTP() iLoad = iLoadHTTP; } } else if (ADV_TWOP_PORT_SSL == iPort) { // gestire un server SSL iLoadSSL = getLoadSSL(iConnectTime, caller); // richiamare il carico per SSL ADV_nte nteSSL = new ADV_nte(sCluster, iPort, sServer, iLoadSSL); putNte(htTwopSSL, "SSL", sHashKey, nteSSL); // salvare le info sul carico SSL. ADV_nte nteHTTP = getNte(htTwopHTTP, "SSL", sHashKey); // richiamare le informazioni // HTTP if (null != nteHTTP) { if (true == nteHTTP.isCurrent(this)) { // controllare il formato orario if (ADV_HOST_INACCESSIBLE != nteHTTP.getLoadValue()) { // HTTP // funziona? iLoad = iLoadSSL; } else { // il server HTTP non funziona, quindi SSL viene contrassegnato // come inattivo iLoad = ADV_HOST_INACCESSIBLE; } } else { // informazioni scadute da HTTP, pertanto SSL viene contrassegnato come // inattivo iLoad = ADV_HOST_INACCESSIBLE; } } else { // nessuna informazione di carico HTTP, riportare // i risultati getLoadSSL() iLoad = iLoadSSL; } } //-------- // gestore errori else { iLoad = ADV_HOST_INACCESSIBLE; } return iLoad; } }