Glassfish Cluster: LoadBalancer with Apache

Glassfish Cluster: LoadBalancer with Apache
G.Morreale

Introduzione:

Il loadbalancer, ha il compito di ripartire il traffico tra i diversi nodi del cluster.

La ripartizione del carico tra i vari nodi del cluster può essere realizzata in diversi modi:
LVS, mod_jk, plugin di glassfish, Rewrite Rule su Apache, usando dell'hardware dedicato etc. etc.
L'obiettivo è comunque quello di interrogare i diversi nodi secondo un determinato algoritmo in modo da caricare i vari nodi secondo le esigenze del sistema.

Nei passi successivi si fà riferimento alla configurazione di un LoadBalancer che sfrutta il plugin di glassfish che considera come ripartitore di traffico il webserver apache.

Usare la soluzione "plug-in" comparta i seguenti vantaggi:

- Integrazione con l'application server
- Possibilità di configurazione di loadbalancing direttamente da admin console:
- Sistema di integrato di Health Checking, il modulo infatti determina se un istanza non è in grado di rispondere al fine di eliminarla dal processo di ripartizione di carico.


- Configurazione dell'algoritmo di ripartizione del carico, con possibilità di caricare un modulo user-defined.

- Configurazione automatica del modulo di balancing, il plugin consente di esportare automaticamente o manualmente il file di configurazione per il modulo in modo da metterlo a corrente, anche in real-time, sulla struttura del cluster (ad es. aggiunta o eliminazione dei nodi).


Premessa:

La comunicazione tra il webserver che agisce da loadbalancer e il DAS avviene tramite SSL.
E' necessario quindi abilitare sul server apache il supporto per SSL.

Il plugin per glassfish considerato è compatibile con apache 2.0.x(versione 32 bit),
quindi non usare la più recente 2.2 o successive.

I passi da eseguire si dividono nelle seguenti macro-operazioni:

  • Installare e Configurare Apache con supporto SSL
  • Installare il plugin e configurare Apache affinchè comunichi con il plugin
  • Creare e abilitare il plugin all'interno del DAS


Installare e Configurare Apache con supporto SSL

I seguenti passi si riferiscono alla piattaforma Windows:
Per Linux o Solaris è possibile seguire una delle molteplici guide sul web o in alternativa consultare la guida fornita dalla sun

Scaricare una versione di Apache con openssl:

  • Abilitare il modulo su httpd.conf togliendo il commento '#'

LoadModule ssl_module modules/mod_ssl.so


  • Assicurarsi dell'esistenza in httpd.conf delle seguenti righe

<IfModule mod_ssl.c>
   Include conf/ssl.conf
</IfModule>


  • Generare il certificato e la chiave per apache

%ApacheDIR%bin openssl.exe req -new -x509 -keyout newreq.pem -out newreq.pem -days 365 -config "%ApacheDIR%confopenssl
.cnf"
(sostituire opportunamente la path per il file openssl.cnf usato)
nota: la generazione del certificato crea dei problemi con la variabile di ambiente che indica la locazione della configurazione openssl, meglio usare lo switch -config come nell'esempio.


ATTENZIONE: il common name richiesto deve corrispondere all'hostname usato su apache. Tale valore corrisponderà poi durante la configurazione del plug in su glassfish al device host.


  • Aprire con un editor di testo il file newreq.pem

  • copiare la porzione che và da 

-----BEGIN CERTIFICATE----- 
a
-----END CERTIFICATE-----

nel file %ApacheDIR%/conf/ssl.crt/server.crt

copiare invece la porzione che và da 
-----BEGIN RSA PRIVATE KEY----- 
a
-----END RSA PRIVATE KEY-----

nel file %ApacheDIR%/conf/ssl.key/server.key


Nota: Se è stata immessa una passphrase durante la generazione della chiave, il file server.key avrà una versione crittografata della chiave. Apache dovrebbe quindi mostrare durante l'avvio una finestra di dialogo per la digitazione della passphrase.
Tale finestra di dialogo NON è supportata in windows, quindi bisogna eliminare la passphrase dalla chiave con il seguente comando:

%ApacheDIR%/bin/openssl rsa -in server.key -out serverNoPhrase.key

Il serverNoPhrase.key ottenuto è senza passaphrase. Assicurarsi che nel file ssl.conf si punti a tale file piuttosto che a quello crittografato oppure ricopiare serverNoPhrase.key in server.key e cancellare serverNoPhrase.key.
.

  • Avviare Apache in SSL mode. In windows il comando è il seguente:
apache -D SSL

  • Testare il funzionamento di apache ssl con il browser non dimenticando di usare https.

ATTENZIONE: Ci potrebbero essere dei conflitti nell'uso delle porte tra glassfish e apache.
Leggendo i log (error.log in apache) o (server.log in glassfish) identificare il conflitto e operare di conseguenza.



Installare il plugin e configurare Apache affinchè comunichi con il plugin

  • Scaricare il plugin dai seguenti link: 

SOLARISX86    http://download.java.net/javaee5/external/SunOS_X86/aslb/jars/aslb-9.1-MS4-b1.jar
SOLARIS       http://download.java.net/javaee5/external/SunOS/aslb/jars/aslb-9.1-MS4-b1.jar
WINDOWS     http://download.java.net/javaee5/external/WINNT/aslb/jars/aslb-9.1-MS4-b1.jar
LINUX            http://download.java.net/javaee5/external/Linux/aslb/jars/aslb-9.1-MS4-b1.jar

nota: navigare su http://download.java.net/javaee5/external/ per ricercare eventuali versioni più recenti o altre piattaforme supportate

In questa configurazione è stato utilizzato "aslb-9.1-MS4-b7.jar"

  • Scompattare il file .jar usando il comando jar -xvf nomefile.jar o utilizzando un archiver come WinRar.
  • I file zip ottenuti (SUNWaslb.zip e SUNWaspx.zip) devono essere scompattati all'interno della cartella lib/lbplugin dell'application server
quindi creare la cartella "lbplugin" su %GLASSFISH_HOME/lib/ e scompattare il contenuto all'interno dei due file .zip

nota: in linux assegnare i permessi con il comando: chmod -R 755 <GLASSFISH_HOME>/lib/lbplugin/lib

  • Copiare il file mod_balancer.dll presente in <GLASSFISH_HOME>/lib/lbplugin/lib/webserver-plugin/windows/apache2/
all'interno della directory modules di Apache.

  • Creare e copiare all'interno di %ApacheDir%/modules/resource i file .res presenti in <GLASSFISH_HOME>/lib/lbplugin/lib/webserver-plugin/windows/apache2/

  • Creare e copiare all'interno di %ApacheDir%/modules/errorpages i file presenti in <GLASSFISH_HOME>/lib/lbplugin/lib/webserver-plugin/windows/apache2/errorpages

  • Creare e copiare all'interno di %ApacheDir%/sec_db_files i file .db presenti in <GLASSFISH_HOME>/lib/lbplugin/lib/webserver-plugin/windows/apache2/

  • Copiare all'interno di %ApacheDir%/conf il file loadbalancer.xml.example presente in <GLASSFISH_HOME>/lib/lbplugin/lib/install/templates/loadbalancer.xml.example 
e rinominarlo loadbalancer.xml

  • Riavviare Apache in modalità SSL



Creare e abilitare il plugin all'interno del DAS

E' consigliabile in questa fase del setup aprire delle console in grado di leggere in tempo reale i contenuti dei file di errori dei log (server.log per glassfish e error.log per apache, inoltre nel caso del cluster leggere non solo il server.log del dominio ma anche quello di nodi e istanze varie)

Effettuare il login sull'admin console del DAS, posizionarsi sull'icona HTTP Load Balancers e Cliccare su New per creare un nuovo riferimento al load balancer.


  • Scegliere un nome per il load balancer, ad esempio apacheLB
  • Indicare come Device Host, l'hostname di apache lo stesso presente nella configurazione ssl.conf, lo stesso digitato nel common name durante la creazione del file newreq.pem (certificato + chiave)
  • Indicare come Devce Admin Port, il numero di porta ssl di apache (di default è 443)
  • Selezionare il corretto target in modo che il loadbalancer punti sul cluster
  • Il checkbox Automatically Apply Changes può essere selezionato se si vuole notificare automaticamente al modulo di balancing di apache riguardo ai cambiamenti di struttura del cluster (es. aggiunta o eliminazione di nodi istanza)
  • Dopo il salvataggio testare la configurazione selezionando apacheLB e cliccando su Test Connection

Nota: Nella sezione Export del LoadBalancer esiste la possibilità di esportare il file di configurazione loadbalancer.xml necessario al modulo di balancing di apache o modificarlo direttamente cliccando su "Apply Changes Now".
Riguardo la generazione automatica del file xml sulla directory di apache su linux bisogna settare correttamente i vari permessi.

Accertarsi inoltre che le istanze all'interno del cluster abbiano abilitato il load balancing (Cliccare sul "Enable Load Balancing" come da immagine)

Il Plug In è configurato.

Installare un applicazione su cluster e verificare dal browser se risponde uno dei nodi richiamando

http://apache_hostname/path_applicazione_cluster

Nota: la configurazione che è stata realizzata usa SSL per la comunicazione tra DAS e apache, Il load balancing invece avviene usando il normale protocollo http.

Possibili Problemi

Provando a inoltrare richieste ripetute verso il loadbalancer si potrebbero verificare i seguenti errori (vedi error.log di apache)

[warn] lb.runtime: RNTM2024: Daemon http://MOBISERVER:38081 is unhealthy.
[warn] lb.runtime: RNTM2030: Daemon Monitor : http://MOBISERVER:38081 : could be because daemon is down
[warn] lb.runtime: RNTM2025: Daemon http://mobipc:38080 is healthy.
[warn] lb.runtime: RNTM2025: Daemon http://mobipc:38080 is healthy.
[warn] lb.runtime: RNTM2025: Daemon http://mobipc:38080 is healthy.
[warn] lb.healthchecker: HLCK3003: Listener: http://MOBISERVER:38081 is detected to be still unHealthy in cluster: cluster
[warn] lb.healthchecker: HLCK3003: Listener: http://MOBISERVER:38081 is detected to be still unHealthy in cluster: cluster
[warn] lb.healthchecker: HLCK3003: Listener: http://MOBISERVER:38081 is detected to be still unHealthy in cluster: cluster
[warn] lb.healthchecker: HLCK3003: Listener: http://mobipc:38080 is detected to be still unHealthy in cluster: cluster
[warn] lb.healthchecker: HLCK3003: Listener: http://mobipc:38080 is detected to be still unHealthy in cluster: cluster

Se le istanze del cluster sono nello stato running e rispondo se chiamate direttamente sui rispettivi ip:porta vuol dire che potrebbe esserci qualche problema nell'httpd.conf, è necessario infatti controllare che i virtual host e server name vari abbiano il corretto nome.

Inoltre il file error.log di Apache viene continuamente aggiornato dal modulo mod_balancer, quindi provvedere opportunamente alla rotazione automatica del file di log oppura a impostare un log-level diverso.

Link di riferimento:


Glassfish Cluster and EJB Timer

Glassfish Cluster and EJB Timer
G.Morreale

Introduzione:

Una delle caratteristiche delle specifiche ejb, è il servizio "Timer Service".
Esso consente di attivare timer per determinati periodi di tempo o allo scadere di determinate date.


Tale servizio si appoggia su un database embedded in glassfish.
Navigando nell'admin console tra i connection pool (vedi risorse JDBC) è possibile notare infatti il connection pool "__TimerPool" utilizzato dalla risorsa __TimerPool.

Tale risorsa è disponibile di default solo per il target "server", quindi il cluster non è nemmeno a conoscenza di un db in grado di supportare il timer service.

Inoltre il database embedded non risulta adeguato in quanto le istanze del cluster non possono accedere a tale db e conoscere quindi lo stato della gestione del timer service.

Dovendo distribuire su glassfish cluster un EJB che utilizza il timer service bisogna configurare un db esterno in grado di supportare le transazioni e garantire che solo un istanza gestisca il timeout senza replicare gli eventi più del necessario.

Passi per la Configurazione:

Per configurare il cluster affinchè esso supporti il servizio EJB Timer è necessario seguire i seguenti passi

- Creare un db (es. TIMER_DB)

- Creare all'interno una tabella usando gli script sql che si trovano all'interno di $GLASSFISH_HOME/lib/install/databases
   Lo script mysql non è presente lo potete copiare da qui:

CREATE TABLE EJB__TIMER__TBL (
    CREATIONTIMERAW      BIGINT        NOT NULL,
    `BLOB`               BLOB,
    TIMERID              VARCHAR(255)  NOT NULL,
    CONTAINERID          BIGINT        NOT NULL,
    OWNERID              VARCHAR(255)  NOT NULL,
    STATE                INTEGER       NOT NULL,
    PKHASHCODE           INTEGER       NOT NULL,
    INTERVALDURATION     BIGINT        NOT NULL,
    INITIALEXPIRATIONRAW BIGINT        NOT NULL,
    LASTEXPIRATIONRAW    BIGINT        NOT NULL,
    CONSTRAINT PK_EJB__TIMER__TBL PRIMARY KEY (TIMERID) 
) ;

nota: il nome della tabella deve essere maiuscolo

- Creare all'interno di "Resource->Connection Pools" un pool in grado di comunicare con il db creato.

- Creare una risorsa jdbc che punta al connection pool appena creato.
La risorsa creata deve avere come target il cluster, per garantire ciò è possibile creare la risorsa cliccando su 
"Cluster->nome cluster->Resources->New->JDBC Resources"

- Andare sulla configurazione del cluster (Quella di default si chiama cluster-config), 
selezionare EJB-container, 
cliccare su EJB Timer Service 
settare nel campo Timer Datasource il nome della risorsa jdbc creata nel passo precedente.

- Riavviare il cluster.

Driver XA  e Possibili problematiche

Per fare un buon setup bisogna creare, come peraltro ho suggerito precedentemente, una risorsa jdbc apposita per il timer.
Tale scelta però può creare dei problemi nel momento in cui l'applicazione che fà uso del timer service contemporaneamente accede ad una risorsa jdbc differente (ad esempio mediante hibernate si effettua l'accesso al connection pool del db dell'applicazione).

In tal caso uno stesso bean deve accedere a due risorse contemporaneamente e garantire le proprietà ACID.
Per far ciò è necessario disporre di un driver JDBC XA-capable

Tale driver ovviamente deve essere disponibile nel classpath, ad esempio copiandolo nella directory /lib del dominio (di default domain1).
(nota: quando aggiorni una libreria è necessario riavviare l'application server)

Nel caso di mysql, il connector J (attualmente alla versione 5.1.6) è XA compatibile.

Oltre ad avere un driver con le suddette caratteristiche è necessario impostare il connection pool affinchè tali caratteristche vengano usate.
Quindi nel connection pool creato si dovrà settare come Resource Type "java.sql.XADataSource", nel campo DataSourceClassName invece bisognerà settare il corretto valore in base al dbms utilizzato

Nel caso di mysql tale classe è 
com.mysql.jdbc.jdbc2.optional.MysqlXADataSource


Purtroppo al momento il connector J crea dei problemi dovuti al bug:http://bugs.mysql.com/bug.php?id=35489

Di conseguenza durante il riavvio del timer (Ad esempio quando viene riavviata un instanza del cluster) si otterà la seguente eccezione:

INFO: Exception thrown from bean; nested exception is: java.lang.IllegalArgumentException: null source jav... 

Caused by: java.lang.IllegalArgumentException: null source
at java.util.EventObject.<init>(EventObject.java:38)
at javax.sql.StatementEvent.<init>(StatementEvent.java:39)
at
com.mysql.jdbc.jdbc2.optional.JDBC4PreparedStatementWrapper.close(JDBC4PreparedStatementWr
apper.java:70)
at com.caucho.sql.UserStatement.close(UserStatement.java:127)
at com.caucho.sql.UserPreparedStatement.close(UserPreparedStatement.java:450)
at org.hibernate.jdbc.AbstractBatcher.closePreparedStatement(AbstractBatcher.java:534)

causata dal bug in questione.

Al fine di risolvere la problematica, in attesa di una nuova release è possibile utilizzare una nightly build del connector j che prevede la correzione del bug.
(nota: quando si reinstalla una libreria jar in glassfish bisogna riavviare).

Io ho risolto con quella del 20 settembre.



Setup di Glassfish Cluster

Glassfish Cluster
G.Morreale

Introduzione:

Un cluster in genere è costituito da una macchina che funge da amministratore e una serie di nodi che svolgono il lavoro delle applicazioni installate su di essi.
L'obiettivo di un cluster di solito è quello di migliorare la scalabilità e l'alta affidabilità del sistema.

La macchina che agisce come amministratore nel glassfish clustering viene chiamata DAS (Domain Administrator Server). 

Ciascuno dei nodi invece è costituito da 2 elementi:

1) Node Agent: Gestisce il ciclo di vita dell'istanza al quale è associato.
2) Istanza: Istanza dell'application server..

Le applicazioni si installano sul DAS e vengono automaticamente propagate nei nodi.


Supporto Cluster

Il supporto cluster deve essere installato solo sulla macchina DAS.


Il glassfish può essere installato direttamente con il supporto cluster attivo oppure è possibile attivarlo anche in seguito a un'installazione standard.

  • Per attivare il supporto in fase di installazione usare il seguente comando: % libantbinant -f setup-cluster.xml al posto di % libantbinant -f setup.xml

  • Per attivare il supporto in seguito (vedi immagine sopra):
    • - Aprire l'admin console
    • - Selezionare tra i common task: Enable Cluster Support
    • - Cliccare su Ok


E' stata predisposta in questo modo la macchina che costituirà il DAS.

Setup Cluster con un nodo

Si supponga di voler creare un cluster minimale (non ha senso in situazioni reali):

Un unica macchina sarà DAS e unico nodo (in seguito aggiungiamo il secondo nodo).

Sulla macchina(DAS) nella quale è stato attivato il supporto cluster si crei il primo nodo.

nota: I nodi si possono creare solo da linea di comando. Dal pannello si può aggiungere un nodo ma è solo un placeholder.. ovvero una predisposizione alla creazione vera e propria

Creazione Node Agent

Da linea di comando digitare:

asadmin create-node-agent nodoDAS

nodoDAS è il nome che si è scelto per il node agent presente sulla macchina DAS.
Con questo comando viene creato un node agent sulla macchina DAS.

Una volta creato deve essere avviato con il seguente comando:

asadmin start-node-agent nodoDAS

Creazione Cluster

Da pannello adesso si procede con la creazione del cluster.

Andare sull'icona Clusters e cliccare sul buttone new per creare un cluster.


Riguardo la configurazione che avrà il cluster lasciando le opzioni su "Configuration" inalterate si creerà una copia della configurazione
default-config, il sistema chiamerà tale copia "cluster-config". Da questo momento sarà possibile configurare diversamente ciò che riguarda il cluster differenziandolo da ciò che riguarda l'istanza stand-alone agendo sulle diverse configurazioni.

Creazione istanza

Una volta creato il cluster si  procede aggiungendo la prima istanza e associandola al nodoDAS.
Si chiami tale istanza istanzaDAS.
Al fine di procedere con la creazione cliccare sul cluster appena creato (si trova all'interno della voce Clusters, nell'immagine precendete ne esiste già uno chiamato cluster), cliccare successivamente sul tab Instances e poi su New.
Indicare il nome instanzaDAS e associarla al NodeAgent nodoDAS dopo cliccare su ok.

Si è appena creata un istanza associata al nodo precedentemente creato, di default ad ogni stop and start del nodo corrisponderà analoga operazione sull'istanza creata.

Stato del Cluster

Facendo un riepilogo su ciò che finora è stato realizzato, ci ritroviamo con una macchina che funge da DAS sulla quale c'è il nodeAgent principale che controlla una sola istanza(instanceDAS).


Aggiunta Secondo Nodo

Per dare un senso al cluster si aggiunga un secondo nodo.

Nota: non è necessario il supporto cluster su questa seconda macchina.

I passi necessari per raggiungere questo obiettivo sono:

1) creare il node agent

usare il comando asadmin sulla macchina sulla quale vogliamo creare il secondo nodo:

asadmin create-node-agent --host macchinaDAS nodo1

il comando è equivalente a quello usato per creare nodoDAS ma questa volta si devono aggiungere dei parametri per indicare alla funzione di creazione(create-node-agent) del nodo agent che la macchina sulla quale risiede il DAS non è localhost(valore di default) ma è un altra macchina.
Nel comando usato si suppone che la macchina sulla quale è installato il DAS abbia come hostname macchinaDAS.

NOTA BENE: E' consigliabile usare un hostname piuttosto che il numero ip, le api jmx potrebbero creare qualche problema.
Non dimenticare su linux di modificare il file /etc/hosts/ con l'hostname scelto.

NOTA: Quando viene richiesto admin user name e admin password durante la creazione del nodo immettere le credenziali relative al login su DAS.

Il nodo creato è stato chiamato nodo1.

2) avviare il nodo

lanciare dalla console della macchina con il nodo1 il comando

asadmin start-node-agent nodo1

in modo da avviare il nuovo node agent.


3) creare l'istanza1 sulla macchina con nodo1

Tale operazione può essere eseguita invece dal pannello.
Andando sul cluster e aggiungendo come fatto precedentemente per instanzaDAS una nuova istanza associandola al node agent nodo1.

l'istanza creata la chiamiamo istanza1

4) avviare istanza1

Cliccare su cluster, cliccare su istanza1, cliccare su "start instance".


Adesso abbiamo due macchine

macchina DAS: con il DAS, un istanza (istanzaDAS), il node Agent principale (nodeAgentDAS).
macchina 1: con un instanza (instanza1), il node Agent corrispondente nodo1.

Avviare il Cluster

Operazione fattibile dal pannello del DAS.

Cliccare su cluster e su "Start Cluster".

Testare Il Cluster

Per testare il cluster è possibile usare un'applicazione di esempio fornita con il glassfish stesso.
Il file ear dovrebbe risiedere all'interno della cartella samples/quickstart/clusterjsp.

Effettauare il deploy dal pannello prestando attenzione al target sul quale si installa l'applicazione.
Bisogna rimuovere il target server e aggiungere invece il target cluster.

Selezionare il flag Availability nel caso in cui l'applicazione faccia uso delle sessioni e tali sessioni devono essere replicate nei diversi nodi del cluster.

Se tutto è andato bene l'applicazione dovrebbe risultare installata su entrambe le macchine.
Per verificare ciò digitare sul browser il seguente url:

http://localhost:38080/clusterjsp

sia dalla macchina DAS che dalla macchina 1.

NOTA: Come è possible notare dall'url le istanze del cluster ascoltano sulla porta 38080 e non su 8080. Su 8080 invece è in ascolto l'istanza standalone dell'application server che nonostante il cluster resta comunque funzionante. Ovviamente se non necessaria è possibile fermarla e usare solo le istanze configurate all'interno del cluster.



Link: