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