La premessa a questo articolo è che tratteremo argomenti un tantino
complessi che presuppongono un po' di background, almeno teorico, per
poter comprendere alcuni termini e concetti.
Qualche tempo fa ho fatto un po' di esperimenti con Glassfish3
cercando di configurare un cluster di application server che
sfruttasse al meglio anche le code JMS. Parliamo quindi di un MOM
(Message Oriented Middleware).
Dalla
documentazione Oracle
(http://docs.oracle.com/cd/E26576_01/doc.312/e24934/jms.htm)
vengono descritti 2 differenti scenari a seconda che si voglia
garantire solo la disponibilità del servizio o anche preservare la
disponibilità dei dati.
In
questo secondo caso si parla di “enhanced broker cluster” (da
adesso in poi, EAC). Il manuale apposito
(http://docs.oracle.com/cd/E26576_01/doc.312/e24949/broker-clusters.htm#ggsxf)
descrive ancora più in dettaglio le sue caratteristiche.
Riporto qui per semplicità solo la figura in modo da evidenziare le
caratteristiche salienti:
In sostanza configuro un broker locale all'interno di ciascun nodo
del mio cluster in modo che ogni istanza del cluster avvii il suo
broker.
Tutti i broker del cluster condividono i dati di configurazione e lo
stato in cui si trovano attraverso un database master. Anche i dati
inseriti all'interno delle nostre code sono persistenti all'interno
del database quindi in caso di fault da parte di uno dei nostri
broker è sempre possibile per un altro di essi riprendere il lavoro
da dove si era interrotto.
Ovviamente a questo punto della vicenda, il nostro tallone d'Achille
diventa il database ma in figura si parla di “Highly available data
store” quindi in base alle funzionalità offerte dal vostro DB
vendor preferito occorrerà mettere in piedi un sistema di failover
del database o una configurazione in replica o qualunque altra cosa
vi permetta di risolvere il problema.
Se il tema generale è chiaro allora possiamo passare alla parte
operativa di creazione e configurazione.
Best practice: creazione e configurazione di un utente ad hoc
Questo primo punto è una banalità ma lo voglio sottolineare perchè
molto spesso non viene rispettato e magari le applicazioni vengono
lanciate da root (non dite di no!) o da un utente più o meno
casuale.
Il vantaggio di creare l'utente dedicato, in questo caso “glassfish”,
mi permette di rintracciare i processi più facilmente, di lavorare
in un ambiente dedicato con tutte e sole le configurazioni di cui ho
bisogno.
Nel mio caso specifico, all'interno della home vado a creare il file
.profile con le seguenti variabili di sistema:
export GLASSFISH_HOME=/home/glassfish/glassfish3
export MQ_HOME=/home/glassfish/glassfish3/mq
export JAVA_HOME=/home/glassfish/java
PATH="$JAVA_HOME/bin:$GLASSFISH_HOME/bin:$MQ_HOME/bin:$PATH"
I path che vedete sono dei link simbolici che puntano alle reali
cartelle di installazione. In alternativa potete anche mettere tutto
nella home, dipende da che tipo di ordine volete ottenere sul vostro
server ;-)
Passo1: Creazione del dominio
Il mio approccio alla configurazione del cluster è stato quello di
usare tanto i tool a riga di comando quanto la console di
amministrazione di Glassfish.
Per la creazione del dominio ho usato il comando “asadmin”:
lcianci@lcianci-dell:/pto/AppServer/glassfish3/bin$ ./asadmin
Use "exit" to exit and "help" for online help.
asadmin>
Una volta entrati in asadmin, passo a creare un nuovo dominio
specificandone il nome
asadmin> create-domain hlite
Enter admin user name [Enter to accept default "admin" / no
password]> hlite
Enter the admin password [Enter to accept default of no password]>
Enter the admin password again>
Using default port 4848 for Admin.
Using default port 8080 for HTTP Instance.
Using default port 7676 for JMS.
Using default port 3700 for IIOP.
Using default port 8181 for HTTP_SSL.
Using default port 3820 for IIOP_SSL.
Using default port 3920 for IIOP_MUTUALAUTH.
Using default port 8686 for JMX_ADMIN.
Using default port 6666 for OSGI_SHELL.
Using default port 9009 for JAVA_DEBUGGER.
The file in given locale [it_IT] at:
[/pto/AppServer/glassfish3/glassfish/lib/templates/locales/it_IT/index.html]
could not be found. Using default (en_US) index.html instead.
Distinguished Name of the self-signed X.509 Server Certificate is:
[CN=lcianci-dell,OU=GlassFish,O=Oracle Corporation,L=Santa
Clara,ST=California,C=US]
Distinguished Name of the self-signed X.509 Server Certificate is:
[CN=lcianci-dell-instance,OU=GlassFish,O=Oracle Corporation,L=Santa
Clara,ST=California,C=US]
No domain initializers found, bypassing customization step
Domain hlite created.
Domain hlite admin port is 4848.
Domain hlite admin user is "hlite".
Command create-domain executed successfully.
Best practice: Creazione di un file per l'autenticazione (opzionale)
Dato che per agire con “asadmin” all'interno del mio nuovo
dominio dovrò sempre connettermi specificando utente e password, mi
semplifico un po' la vita creando il file hlite_passwd che contiene
all'interno due variabili:
AS_ADMIN_USER=hlite
AS_ADMIN_PASSWORD=hlite
Queste ovviamente sono le credenziali che ho inserito al passo1 in
fase di creazione del dominio.
In questo modo evito di inserire le credenziali ogni volta e posso
collegarmi in questo modo:
asadmin -W hlite_passwd
Passo2: Avvio del dominio
Passo semplice e indolore:
asadmin> start-domain hlite
Waiting for hlite to start .....
Successfully started the domain : hlite
domain Location: /pto/AppServer/glassfish3/glassfish/domains/hlite
Log File:
/pto/AppServer/glassfish3/glassfish/domains/hlite/logs/server.log
Admin Port: 4848
Command start-domain executed successfully.
Se siamo curiosi e vogliamo esplorare la nostra console la troviamo
su localhost:4848.
Passo3: Creazione dei nodi applicativi del cluster
Il cluster che ho in mente per i miei test è composto da due nodi:
la mia macchina e un server remoto. Il nodo master, dal quale accedo
eventualmente alla console è la mia macchina.
Una volta creato il dominio, andiamo quindi a configurare il primo
nodo, quello di default, che è appunto localhost
asadmin> list-nodes-config
localhost-hlite CONFIG localhost
Command list-nodes-config executed successfully.
Creiamo invece un nodo ssh per usare la nostra macchina di sviluppo
remota. Per questo secondo passo di creazione del nodo uso
direttamente la console di amministrazione dato che a questo punto è
ormai up&running.
Passo4: Creazione del database per i broker JMS
Creo il mio database master sulla macchina remota di sviluppo
utilizzando mysql:
mysql> create database glassfish_mq;
Query OK, 1 row affected (0.00 sec)
Ricordatevi di creare l'utente e assegnare le grant:
mysql> grant all on glassfish_mq.* to glassfish@'%' identified by
'glassfish';
Query OK, 0 rows affected (0.00 sec)
Passo5: Caricamento delle librerie per il database
Affinchè la rete di broker JMS possa accedere al nostro database,
occorre copiare le librerie mysql (il JAR) in questa cartella:
GLASSFISH_HOME/mq/lib/ext/
Passo6: Configurazione del cluster jms enhanced
Occorre configurare e definire i broker di tipo LOCAL e non EMBEDDED
per entrambi i due nodi, quello locale e quello remoto.
Per fare questo uso la console. (proprietà JMS del file di
configurazione del cluster)
Una volta completata l'operazione, possiamo tornare alla riga di
comando di asadmin:
asadmin> configure-jms-cluster --passwordfile hlite_passwd
--clustertype=enhanced --dbvendor mysql --dbuser glassfish --dburl
jdbc:mysql://IP_SERVER_DB:3306/glassfish_mq clop-hlite
JMS Cluster Configuration updated for Cluster clop-hlite
Command configure-jms-cluster executed successfully.
Tutto chiaro?
Il mio dominio si chiama HLITE mentre il cluster applicativo si
chiama CLOP-HLITE.
Adesso passiamo alle istanze dei nodi.
Passo7: Creazione e avvio delle istanze sul cluster
Uso la console per creare 4 istanze, 2 locali e 2 remote che chiamo:
- local-cl01, local-cl02
- remote-cl01, remote-cl02
A questo punto, sempre utilizzando la console di amministrazione,
fate partire il cluster avviando soltanto la prima istanza locale.
Se tutto va bene dovrebbe partire correttamente e guardando i log vi
accorgerete che sono state create le tabelle sul database di
configurazione.
Scoprirete
anche che il broker name di questa prima istanza è il seguente:
clophlitelocalcl01@lcianci-dell
e risponde alla porta 27676.
Ripetete l'operazione per le altre istanze.
Avremmo potuto far partire direttamente l'intero cluster ma così
abbiamo controllato la corretta creazione del database e l'avvio di
un singolo broker.
Passo8: Definizione delle risorse JMS
Adesso, dalla console di amministrazione , andiamo a configurare le
risorse JMS usando l'apposito TAB.
Creiamo la nostra QueueConnectionFactory (QCF) e gli oggetti Queue
che andremo ad usare ricordando che occorre impostare per ciascuno il
target cluster.
Il nome della QCF sarà quello che poi andremo ad usare all'interno
delle applicazioni di test.
Passo9: Deploy delle applicazione di test (EAR, EJB e WAR)
Per testare il tutto può bastare una semplice applicazione
enterprise (modulo EAR) con dentro una servlet (modulo WAR) che
accoda i messaggi quando la chiamate e un MessageDrivenBean (modulo
EJB) che scoda i messaggi restando in ascolto sulla coda.
Per il deploy del modulo EAR usiamo naturalmente la console.
Passo10: Test e verifiche
Una volta che le applicazioni di test sono installate sulle 4
istanze, vi basterà creare un semplice script di shell o una suite
Jmeter per andare a chiamare ripetutamente le vostre servlet e
simulare quindi le chiamate applicative.
Per verificare che a livello dei broker tutto funzioni correttamente,
possiamo usare un altro utile tool a riga di comando “imqcmd”
ricordando che occorre impostare preventivamente utente e password
jms mediante la console alla voce “provider jms”. In particolare
ecco 3 utili comandi:
imqcmd list bkr -u admin -b lcianci-dell:27676
imqcmd query bkr -u admin -b lcianci-dell:27676
imqcmd query dst -t q -n sampleQueue -u admin -b lcianci-dell:27676
Gli attributi sono abbastanza espliciti ma ad ogni modo:
-u: utente
-b: broker (nome macchine + porta)
-t: tipo della destination [Queue (q) oppure Topic (t)]
-n: nome della destination (la mia coda di test)
Ecco quindi l'output del mio cluster enhanced mentre viene bombardato
dal mio script sh di test:
imqcmd list bkr -u admin -b lcianci-dell:27676
Listing all the brokers in the cluster that the following broker is a
member of:
--------------------------------------------------------------------------------------------------------------
ID of broker Time since last
Broker ID Address State Msgs in store
performing takeover status timestamp
--------------------------------------------------------------------------------------------------------------
clophlitelocalcl02 192.168.0.209:27677 OPERATING 278
19 seconds
clophliteremotecl01 192.168.0.19:27676 OPERATING 419
20 seconds
clophlitelocalcl01 192.168.0.209:27676 OPERATING 340
21 seconds
clophliteremotecl02 192.168.0.19:27677 OPERATING 475
13 seconds
Successfully listed brokers in the cluster.
Tips: Deploy e upgrade delle applicazioni con continuità di servizio
Dato il cluster applicativo, diventa molto semplice, anche mentre
eroghiamo il servizio, andare ad aggiornare le applicazioni sui
singoli nodi. Questa ovviamente non è una best practice ma è sempre
meglio sapere come fare. L'ideale è comunque prevedere un minimo di
disservizio e fare le cose con calma.
Per poter effettuare il deploy di una nuova versione del mio EAR mi
basta crearne una copia con un nome leggermente diverso, poi con la
context root continuerò ovviamente a chiamare i componenti
applicativi sempre con le stesse url.
Supponiamo quindi di aver fatto il deploy iniziale del file
TestCode_EAR_1.0.ear
Per aggiornare la versione, ricordiamo che il target in questo caso è
il mio cluster e quindi tramite asadmin:
asadmin deploy --enabled=false --target clop-hlite
/home/lcianci/export/TestCode_EAR_1.1.ear
In questo modo ho caricato la nuova versione dell'ear ma questa non è
ancora attiva.
Disattivo adesso il vecchio ear su una singola istanza. Qui il target
è la mia istanza:
asadmin disable --target local-cl01 TestCode_EAR
Infine attivo il nuovo ear sulla singola istanza
asadmin enable --target local-cl01 TestCode_EAR_1.1
Nel frattempo il mio script di test continua a bombardare il cluster
e adesso, 3 applicazioni su 4 sono vecchie mentre la quarta è
aggiornata.
Conclusioni
Come anticipato, il tema non era semplice e nelle parti relative alla
console ho dato per scontato che chi legge si sappia muovere un
minimo tra i meandri di Glassfish. Immagino che se non sia così
forse non eravate nemmeno interessati al tema.
In generale noto che con la configurazione di base, il cluster non mi
sembra eccessivamente performante però dobbiamo tenere conto che sto
usando due istanze in locale sulla mia macchina.
Sono inoltre fiducioso che seguendo i consigli di fine-tuning della
documentazione si riesca comunque a migliorare le performance.
Il cluster jms enhanced è comunque per definizione meno performante
della sua versione base sia essa master-slave o di tipo peer.
Ovviamente non tutte le circostanze presuppongono l'uso di questo
tipo di MOM quindi occorre sempre valutare per bene i pro e i contro
di una determinata scelta architetturale.
Nessun commento:
Posta un commento