O seguinte exemplo mostra como implementar um orientador de duas portas. Essa amostra de orientador customizado demonstra a capacidade para detectar falha de uma porta de um servidor com base no seu próprio status e no status de um daemon de servidor diferente que está executando em outra porta na mesma máquina servidor.
Por exemplo, se o daemon HTTP na porta 80 parar de responder, você também deverá querer parar o tráfego de roteamento para o daemon SSL na porta 443.
Esse orientador é mais agressivo do que os orientadores padrão porque ele considera qualquer servidor que não estiver enviando uma resposta para parar o funcionamento e marca-o como inativo. Os orientadores padrão consideram os servidores não responsivos como sendo muito lentos. Esse orientador marca um servidor como inativo para a porta HTTP e para a porta SSL com base em uma falta de resposta de uma das portas.
Para usar esse orientador customizado, o administrador inicia duas instâncias do orientador: uma na porta HTTP e outra na porta SSL. O orientador instancia duas hashtable globais estáticas, uma para HTTP e outra para o SSL. Cada orientador tenta se comunicar com o daemon do servidor e armazena os resultados desse evento na hashtable. O valor que cada orientador retorna para a classe do orientador base depende da possibilidade de se comunicar com seu próprio daemon do servidor e da possibilidade de o orientador parceiro se comunicar com seu 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; //-------- // Defina o elemento de tabela para as hashtables usadas nesse orientador customizado 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(); } //-------- // verificar se esse elemento é atual ou expirado public boolean isCurrent(ADV_twop oThis) { boolean bCurrent; int iLifetimeMs = 3 * 1000 * oThis.getInterval(); // set lifetime as // 3 advisor cycles Date dNow = new Date(); Date dExpires = new Date(dTimestamp.getTime() + iLifetimeMs); if (dNow.after(dExpires)) { bCurrent = false; } else { bCurrent = true; } return bCurrent; } //-------- // acessador(res) de valor public int getLoadValue() { return iLoad; } //-------- // clone (evita distorção entre os encadeamentos) public synchronized Object Clone() { try { return super.clone(); } catch (cloneNotSupportedException e) { return null; } } } //-------- // definir o orientador customizado 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 tabelas para manter informações de histórico específicas da porta 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"; //-------- // criar matriz de byte com a mensagem de saudação do cliente SSL public static final byte[] abClientHello = { (byte)0x80, (byte)0x1c, (byte)0x01, // client hello (byte)0x03, (byte)0x00, // SSL version (byte)0x00, (byte)0x03, // cipher spec len (bytes) (byte)0x00, (byte)0x00, // session ID len (bytes) (byte)0x00, (byte)0x10, // challenge data len (bytes) (byte)0x00, (byte)0x00, (byte)0x03, // cipher spec (byte)0x1A, (byte)0xFC, (byte)0xE5, (byte)Ox20, // challenge data (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 times the response setAdvisor ( this ); } //-------- // ADV_AdvisorInitialize public void ADV_AdvisorInitialize() { return; } //-------- // rotinas de acesso PUT e GET sincronizadas para as hashtables 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 carregamento HTTP com base na resposta do servidor int getLoadHTTP(int iConnectTime, ADV_Thread caller) { int iLoad = ADV_HOST_INACCESSIBLE; int iRc = caller.send(ADV_HTTP_REQUEST_STRING); // send request message // to server if (0 <= iRc) { // did the request return a failure? StringBuffer sbReceiveData = new StringBuffer("") // allocate a buffer // for the response iRc = caller.receive(sbReceiveData); // get response from server if (0 <= iRc) { // did the receive return a failure? if (0 < sbReceiveData.length()) { // is data there? iLoad = SUCCESS; // ignore retrieved data and // return success code } } } return iLoad; } //-------- // getLoadSSL() - determinar carregamento SSL com base na resposta do 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); // Perform a receive. socket.getInputStream().read(); // If receive is successful, // return load of 0. We are not // concerned with data's contents, // and the load is calculated by // the ADV_Thread thread. iLoad = 0; } catch (IOException e) { // Upon error, iLoad will default to it. } return iLoad; } //-------- // getLoad - mesclar resultados a partir dos métodos HTTP e SSL. public int getLoad(int iConnectTime, ADV_Thread caller) { int iLoadHTTP; int iLoadSSL; int iLoad; int iRc; String sCluster = caller.getCurrentClusterId(); // current cluster address int iPort = getAdviseOnPort(); String sServer = caller.getCurrentServerId(); String sHashKey = sCluster = ":" + sServer; // hash table key if (ADV_TWOP_PORT_HTTP == iPort) { // handle an HTTP server iLoadHTTP = getLoadHTTP(iConnectTime, caller); // get the load for HTTP ADV_nte nteHTTP = newADV_nte(sCluster, iPort, sServer, iLoadHTTP); putNte(htTwopHTTP, "HTTP", sHashKey, nteHTTP); // save HTTP load // information ADV_nte nteSSL = getNte(htTwopSSL, "SSL", sHashKey); // get SSL // information if (null != nteSSL) { if (true == nteSSL.isCurrent(this)) { // check the time stamp if (ADV_HOST_INACCESSIBLE != nteSSL.getLoadValue()) { // is SSL // working? iLoad = iLoadHTTP; } else { // SSL is not working, so mark the HTTP server down iLoad= ADV_HOST_INACCESSIBLE; } } else { // SSL information is expired, so mark the // HTTP server down iLoad = ADV_HOST_INACCESSIBLE; } } else { // no load information about SSL, report // getLoadHTTP() results iLoad = iLoadHTTP; } } else if (ADV_TWOP_PORT_SSL == iPort) { // handle an SSL server iLoadSSL = getLoadSSL(iConnectTime, caller); // get load for SSL ADV_nte nteSSL = new ADV_nte(sCluster, iPort, sServer, iLoadSSL); putNte(htTwopSSL, "SSL", sHashKey, nteSSL); // save SSL load info. ADV_nte nteHTTP = getNte(htTwopHTTP, "SSL", sHashKey); // get HTTP // information if (null != nteHTTP) { if (true == nteHTTP.isCurrent(this)) { // check the timestamp if (ADV_HOST_INACCESSIBLE != nteHTTP.getLoadValue()) { // is HTTP // working? iLoad = iLoadSSL; } else { // HTTP server is not working, so mark SSL down iLoad = ADV_HOST_INACCESSIBLE; } } else { // expired information from HTTP, so mark SSL down iLoad = ADV_HOST_INACCESSIBLE; } } else { // no load information about HTTP, report // getLoadSSL() results iLoad = iLoadSSL; } } //-------- // manipulador de erros else { iLoad = ADV_HOST_INACCESSIBLE; } return iLoad; } }