Das folgende Beispiel zeigt, wie ein Advisor mit zwei Ports implementiert wird. Dieses Beispiel für einen angepassten Advisor veranschaulicht, wie Fehler für einen Port eines Servers basierend auf dem eigenen Status und dem Status eines anderen Serverdämons, der an einem anderen Port auf derselben Servermaschine ausgeführt wird, erkannt werden können.
Wenn der HTTP-Dämon an Port 80 beispielsweise nicht mehr reagiert, möchten Sie möglicherweise auch keinen Datenverkehr mehr an den SSL-Dämon an Port 443 weiterleiten.
Dieser Advisor ist aggressiver als Standardadvisors, weil er jeden Server, der keine Antwort sendet, als funktionsunfähig betrachtet und deshalb als inaktiv markiert. Standardadvisor stufen nicht reagierende Server als sehr langsam ein. Dieser Advisor markiert einen Server für den HTTP-Port und den SSL-Port als inaktiv, wenn einer der Ports keine Antwort liefert.
Zur Verwendung dieses angepassten Advisors startet der Administrator zwei Instanzen des Advisors: eine für den HTTP-Port und eine für den SSL-Port. Der Advisor instanziiert zwei statische globale Hashtabellen, eine für HTTP und eine für SSL. Jeder Advisor versucht, mit ihrem Serverdämon zu kommunizieren, und speichert die Ergebnisse dieses Ereignisses in seiner Hashtabelle. Der Wert, den jeder Advisor an die Basisadvisorklasse zurückgibt, ist abhängig von der Fähigkeit des Advisors zur Kommunikation mit seinem eigenen Serverdämon und der Fähigkeit des Partneradvisors zur Kommunikation mit dessen Dämon.
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; //-------- // Tabellenelement für die in diesem angepassten Advisor verwendeten Hashtabellen definieren class ADV_nte implements Cloneable { private String sCluster; private int iPort; private String sServer; private int iLoad; private Date dTimestamp; //-------- // Konstruktor public ADV_nte(String sClusterIn, int iPortIn, String sServerIn, int iLoadIn) { sCluster = sClusterIn; iPort = iPortIn; sServer = sServerIn; iLoad = iLoadIn; dTimestamp = new Date(); } //-------- // Prüfen, ob dieses Element aktuell oder abgelaufen ist public boolean isCurrent(ADV_twop oThis) { boolean bCurrent; int iLifetimeMs = 3 * 1000 * oThis.getInterval(); // 3 Advisorzyklen als // Lebensdauer festlegen Date dNow = new Date(); Date dExpires = new Date(dTimestamp.getTime() + iLifetimeMs); if (dNow.after(dExpires)) { bCurrent = false; } else { bCurrent = true; } return bCurrent; } //-------- // Zugriffsmechanismen für Werte public int getLoadValue() { return iLoad; } //-------- // Klonen (Beschädigung zwischen Threads vermeiden) public synchronized Object Clone() { try { return super.clone(); } catch (cloneNotSupportedException e) { return null; } } } //-------- // Angepassten Advisor definieren 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; //-------- // Tabellen für portspezifische Protokollinformationen definieren 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"; //-------- // Bytefeldgruppe mit einer Hello-Nachricht des SSL-Clients erstellen public static final byte[] abClientHello = { (byte)0x80, (byte)0x1c, (byte)0x01, // Client-Hello (byte)0x03, (byte)0x00, // SSL-Version (byte)0x00, (byte)0x03, // Länge der Verschlüsselungsspezifikation (Byte) (byte)0x00, (byte)0x00, // Länge der Sitzungs-ID (Byte) (byte)0x00, (byte)0x10, // Länge der Anforderungsdaten (Byte) (byte)0x00, (byte)0x00, (byte)0x03, // Verschlüsselungsspezifikation (byte)0x1A, (byte)0xFC, (byte)0xE5, (byte)Ox20, // Anforderungsdaten (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 }; //-------- // Konstruktor public ADV_twop() { super(ADV_TWOP_NAME, VERSION, ADV_TWOP_DEF_ADV_ON_PORT, ADV_TWOP_DEF_INTERVAL, "", false); // false = Load Balancer terminiert die Antwort setAdvisor ( this ); } //-------- // ADV_AdvisorInitialize public void ADV_AdvisorInitialize() { return; } //-------- // Synchronisierte PUT- und GET-Zugriffsroutinen für die Hashtabellen 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 - HTTP-Last auf der Basis der Serverantwort bestimmen int getLoadHTTP(int iConnectTime, ADV_Thread caller) { int iLoad = ADV_HOST_INACCESSIBLE; int iRc = caller.send(ADV_HTTP_REQUEST_STRING); // Anforderungsnachricht an // Server senden if (0 <= iRc) { // Hat die Anforderung einen Fehler zurückgegeben? StringBuffer sbReceiveData = new StringBuffer("") // Puffer für die // Antwort zuordnen iRc = caller.receive(sbReceiveData); // Antwort vom Server abrufen if (0 <= iRc) { // Hat receive einen Fehler zurückgegeben? if (0 < sbReceiveData.length()) { // Sind Daten vorhanden? iLoad = SUCCESS; // Abgerufene Daten ignorieren und // Erfolgscode zurückgeben } } } return iLoad; } //-------- // getLoadSSL() - SSL-Last auf der Basis der Serverantwort bestimmen 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); // receive (Empfang) durchführen. socket.getInputStream().read(); // Bei erfolgreichem Empfang // 0 als Lastwert zurückgeben. Der // Dateninhalt spielt keine Rolle, // und die Last wird vom // ADV_Thread-Thread berechnet. iLoad = 0; } catch (IOException e) { // Bei einem Fehler als Standardwert für iLoad verwenden. } return iLoad; } //-------- // getLoad - Ergebnisse der HTTP- und SSL-Methoden zusammenführen public int getLoad(int iConnectTime, ADV_Thread caller) { int iLoadHTTP; int iLoadSSL; int iLoad; int iRc; String sCluster = caller.getCurrentClusterId(); // aktuelle Clusteradresse int iPort = getAdviseOnPort(); String sServer = caller.getCurrentServerId(); String sHashKey = sCluster = ":" + sServer; // Schlüssel für Hashtabelle if (ADV_TWOP_PORT_HTTP == iPort) { // HTTP-Server ausführen iLoadHTTP = getLoadHTTP(iConnectTime, caller); // Last für HTTP abrufen ADV_nte nteHTTP = newADV_nte(sCluster, iPort, sServer, iLoadHTTP); putNte(htTwopHTTP, "HTTP", sHashKey, nteHTTP); // HTTP-Lastinformationen // speichern ADV_nte nteSSL = getNte(htTwopSSL, "SSL", sHashKey); // SSL-Informationen // abrufen if (null != nteSSL) { if (true == nteSSL.isCurrent(this)) { // Zeitmarke prüfen if (ADV_HOST_INACCESSIBLE != nteSSL.getLoadValue()) { // Funktioniert // SSL? iLoad = iLoadHTTP; } else { // SSL funktioniert nicht, deshalb HTTP-Server als inaktiv markieren iLoad= ADV_HOST_INACCESSIBLE; } } else { // SSL-Informationen sind abgelaufen, deshalb // HTTP-Server als inaktiv markieren iLoad = ADV_HOST_INACCESSIBLE; } } else { // Keine Lastinformationen zu SSL, // Ergebnisse von getLoadHTTP() melden iLoad = iLoadHTTP; } } else if (ADV_TWOP_PORT_SSL == iPort) { // SSL-Server ausführen iLoadSSL = getLoadSSL(iConnectTime, caller); // Last für SSL abrufen ADV_nte nteSSL = new ADV_nte(sCluster, iPort, sServer, iLoadSSL); putNte(htTwopSSL, "SSL", sHashKey, nteSSL); // SSL-Lastinformationen speichern ADV_nte nteHTTP = getNte(htTwopHTTP, "SSL", sHashKey); // HTTP-Informationen // abrufen if (null != nteHTTP) { if (true == nteHTTP.isCurrent(this)) { // Zeitmarke prüfen if (ADV_HOST_INACCESSIBLE != nteHTTP.getLoadValue()) { // Funktioniert // HTTP? iLoad = iLoadSSL; } else { // HTTP funktioniert nicht, deshalb SSL als inaktiv markieren iLoad = ADV_HOST_INACCESSIBLE; } } else { // Abgelaufene Informationen von HTTP, deshalb SSL als inaktiv markieren iLoad = ADV_HOST_INACCESSIBLE; } } else { // Keine Lastinformationen zu HTTP, // Ergebnisse von getLoadSSL() melden iLoad = iLoadSSL; } } //-------- // Fehlerbehandlungsroutine else { iLoad = ADV_HOST_INACCESSIBLE; } return iLoad; } }