MokaByte 76 - Luglio Agosto 2003 
Istanze multiple di JBoss 2.4.x
di
Fabrizio Gianneschi
Un modo abbastanza comune per sfruttare al meglio l'hardware a disposizione è quello di eseguire più istanze di uno stesso server nella stessa macchina fisica.
Tipicamente, ogni elaboratore servente è riservato all'esecuzione di una sola istanza di server software e infatti, non a caso, il termine stesso di "server" è utilizzato per riferirsi nello stesso tempo al software (ad esempio Apache HTTP Server) e all'hardware su cui esso gira. Avendo a disposizione un'intera macchina, chiaramente il software è libero (o quasi) di appropriarsi a fondo di tutte le sue risorse (CPU, memoria...).

Introduzione
L'idea di "saturare" una macchina con più di un'istanza dello stesso server software, anzichè duplicare l'hardware e far girare ogni istanza su una macchina dedicata, potrà a qualcuno sembrare strana; tuttavia, esistono delle ragioni ben fondate per le quali spesso si adotta questa tecnica.
Come già accennato in precedenza, uno scopo può essere quello di massimizzare l'utilizzo dell'hardware a disposizione. L'hardware costa, specialmente i sistemi server hardware, e talvolta non si hanno le risorse economiche per affrontare l'acquisto di un nuovo elaboratore.
Il discorso è ancora più azzeccato se si considera che ormai molti software si pagano in base al numero di CPU, per cui mantenere basso il numero delle stesse (pur aumentando le istanze in esecuzione parallela) può essere conveniente. Inoltre, oramai le CPU hanno raggiunto potenze di calcolo assolutamente impressionanti, spesso sovradimensionate, e sono benissimo in grado di servire più istanze contemporanee allo stesso tempo.
Sempre rimanendo nel discorso CPU, usufruire di istanze multiple consente di sfruttare al meglio anche gli elaboratori multiprocessore, magari dedicando una CPU ad ogni istanza.
Infine, non dimentichiamo le situazioni tipiche che devono affrontare i fornitori di servizi di Hosting e Server Condivisi (o Virtuali); per costoro, un rapporto 1:1 tra clienti e macchine dedicate è assolutamente impraticabile.

JBoss clustering
JBoss è un application server che supporta il clustering a partire dalla versione 3.0. Per supporto al clustering si intende il fatto che le varie istanze in esecuzione (che siano su macchine diverse o sulla stessa macchina) sono in grado di colloquiare "dietro le quinte" della nostra applicazione enterprise per scambiarsi informazioni riguardanti lo stato della stessa. Ciò è necessario, poiché per l'utente il cluster è visto nel suo complesso come un unico elaboratore servente, e quindi eventuali modifiche allo stato dell'applicazione che avvengono in un istanza devono essere trasmesse (o condivise) su tutti i nodi del cluster. Un esempio può essere lo stato dei Session Bean Stateful, degli Entity Bean, delle cache.
Tutto questo lavoro, deve essere gestito dal motore di clustering dell'application server in coppia ad un dispositivo di bilanciamento del carico e risultare trasparente ai programmatori.
Le versioni 2.4.x di JBoss, purtroppo, non supportano il clustering nel senso appena descritto; è possibile tuttavia sfruttare almeno il meccanismo delle istanze multiple, che ovviamente non saranno sincronizzate.

Setup di istanze multiple in JBoss 2.4.x
Per eseguire più istanze di JBoss 2.4.x nella stessa macchina, è sufficiente garantire che non ci siano istanze che condividano le stesse porte TCP. JBoss utilizza infatti diverse porte per consentire l'accesso a servizi quali ad esempio il naming (JNDI, porta 1099), o la console JMX (8082). Ogni porta deve risultare ad uso esclusivo di una sola istanza. Pertanto, la strategia adottata in questo esempio sarà quella di individuare tutte le porte utilizzate e garantire l'univocità per ogni istanza.
E' necessario inoltre anche un settaggio diverso per il database Hypersonic che JBoss utilizza internamente per salvare il suo stato e le informazioni del motore di persistenza degli oggetti CMP JAWS; in caso contrario, le istanze condividono il database, dando luogo a probabili e sgradite interferenze. Nel caso, è possibile anche sostituire il database Hypersonic con un altro database di nostra scelta.
La cartella di installazione di JBoss sarà di seguito riferita col nome JBOSS_HOME.
In questo esempio, saranno create due istanze di JBoss, denominate "default" e "clone".
Tutti i problemi strettamente applicativi (es: duplicazione di pool di connessioni, risorse) non sono oggetto del presente documento, anche se è doveroso segnalare che devono essere assolutamente presi in considerazione.

 

Procedura
Creare una cartella clone dentro JBOSS_HOME\conf e copiarci dentro tutto il contenuto della cartella JBOSS_HOME\conf\default.


Figura 1 - Configurazione delle cartelle

In questo modo la configurazione del clone è identica a quella dell'istanza di default.
Vediamo ora dove e come modificare le porte TCP utilizzate. Nell'esempio, aggiungiamo la costante 10000 ad ogni numero di porta utilizzato dall'istanza clone.
Aprire il file JBOSS_HOME\conf\clone\jboss.jcml con un editor di testo:
· Nella sezione Classloading, modificare la porta 8083 del servizio WebServer in 18083.
· Nella sezione JNDI, modificare la porta 1099 del servizio Naming in 11099.
· Nella sezione JDBC, modificare la porta 1476 del servizio Hypersonic in 11476.
· Sempre nella stessa sezione, modificare anche la riga
  <attribute name="URL">jdbc:hsqldb:hsql://localhost:1476</attribute>
  in
  <attribute name="URL">jdbc:hsqldb:hsql://localhost:11476</attribute>

· Nella sezione JMX Adaptors, modificare la porta 8082 del servizio html in 11802.

Veniamo ora ai settaggi relativi agli EJB.
Aprire il file JBOSS_HOME\conf\clone\standardjboss.xml con un editor di testo:
· Cambiare ogni occorrenza dell'elemento

...
<container-invoker-conf>
<RMIObjectPort>4444</RMIObjectPort>
...

in
...
<container-invoker-conf>
<RMIObjectPort>14444</RMIObjectPort>
...

Quest'ultima modifica è da effettuarsi anche in tutti i deployment descriptor proprietari di JBoss (jboss.xml) contenuti nei JAR delle applicazioni, nel caso siano stati effettuati dei settaggi a grana fine per qualche EJB.

 

Esecuzione delle istanze
Le istanze vanno eseguite separatamente, utilizzando il comando run (run.bat in Windows e run.sh in Linux) contenuto nella cartella JBOSS_HOME\bin.
Il nome dell'istanza va specificato come parametro al momento del lancio. Ad esempio:

$:> run clone

oppure, per l'istanza di default

$:> run

Sì può verificare l'istanza in esecuzione controllando semplicemente l'output di JBoss, come in figura:



Figura 2
- Startup dell'istanza clone

Utilizzo delle istanze
Una volta che le istanze sono in esecuzione, possono essere liberamente utilizzate dai client nei modi consueti. Si deve solamente aver cura di riferirsi ad ogni istanza attraverso le porte corrette. Ad esempio, consideriamo il lookup a degli EJB. Per l'istanza di default avremo:

java.util.Properties defaultEnv= new java.util.Properties();
defaultEnv.put("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");

//Per l'istanza di default, JNDI è sulla porta 1099
defaultEnv.put("java.naming.provider.url",
"jnp://localhost:1099");
defaultEnv.put("java.naming.factory.url.pkgs",
"org.jboss.naming:org.jnp.interfaces");

Context defaultCtx = new InitialContext(defaultEnv);
Object pippoRef = ctx.lookup("ejb/PippoBean");

Mentre per l'istanza clone:

java.util.Properties cloneEnv= new java.util.Properties();
cloneEnv.put("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");

//Per l'istanza clone, JNDI è sulla porta 11099
cloneEnv.put("java.naming.provider.url",
"jnp://localhost:11099");
cloneEnv.put("java.naming.factory.url.pkgs",
"org.jboss.naming:org.jnp.interfaces");

Context cloneCtx = new InitialContext(cloneEnv);
Object plutoRef = ctx.lookup("ejb/PlutoBean");

Varianti
La procedura sopradescritta consente di eseguire più istanze mantenendo unica la cartella d'installazione e di deploy. Questo implica che all'interno di ogni istanza saranno in esecuzione le stesse applicazioni delle altre istanze (ovviamente in JVM separate).
Ciò costituisce una limitazione nel caso in cui si voglia destinare un'istanza all'applicazione X e un'altra all'applicazione Y. Per differenziare le applicazioni a seconda dell'istanza, si propongono due varianti:

Variante 1: Installazione multipla
La soluzione più banale è quella di duplicare le installazioni di JBoss. Ferma restando la stessa macchina fisica, si avranno dunque più cartelle d'installazione. Rimane obbligatoria, comunque, la procedura di cambiamento di numerazione delle porte TCP, anche se non è più necessario duplicare la cartella JBOSS_HOME\conf\default, poiché ogni installazione avrà la sua.


Figura 3
- Installazione duplicata

Variante 2: Separazione delle cartelle di deploy
E' possibile specificare nel file JBOSS_HOME\conf\nomeistanza\jboss.jcml il percorso della cartella di deploy, nella sezione Auto deployment:


<attribute name="URLs">../deploy,../deploy/lib</attribute>

In questo modo, ogni istanza può puntare ad una propria cartella di deploy, come visibile in figura:



Figura 4
- Separazione delle cartelle di Deploy>>

Conclusioni
Eseguire più istanze di JBoss sulla stessa macchina comporta senz'altro il vantaggio di non duplicare le installazioni su macchine diverse, realizzando comunque un qualcosa che assume sempre più le sembianze di un cluster (con tutti i distinguo del caso) e massimizzando l'utilizzo delle risorse a disposizione. Come già citato, questa tecnica risolve alcuni problemi presentando costi veramente bassi.
Tuttavia, può comportare anche vari svantaggi; dato che ogni istanza è eseguita su una JVM separata, necessita di una quota di RAM e CPU indipendentemente dalle altre. Abusando di tali risorse in maniera indiscriminata, un sistema potrebbe divenire presto inutilizzabile.
Pur non essendo recentissima, l'architettura 2.4.x di JBoss si conferma un prodotto assolutamente valido, in grado di fornire un utilissimo supporto in fase di sviluppo e, perchè no, anche in fase di produzione se i requisiti lo consentono. La completa configurabilità, modularità e l'essere open source colloca ormai JBoss a livello degli application server commerciali.


Bibliografia
[1] JBoss Group, LLC - "JBoss 2.4.x documentation", http://jboss.sourceforge.net/doc-24/, 2003
[2] Bill Burke - "Clustering with JBoss/Jetty", http://www.onjava.com/pub/a/onjava/2001/09/18/jboss.html , 2001
[3] Renè Muller - "Hands-on Guide to JBoss", University of Applied Sciences Northwestern Switzerland, 2002

Fabrizio Gianneschi, si occupa di tecnologia Java, J2EE e metodologia XP presso Atlantis S.p.A - La Città dell'Innovazione (CA). Svolge attività di formazione, progetto e sviluppo di applicazioni web, content management, e-business e progetti di Ricerca relativi alla Pubblica Amministrazione. Nel (poco) tempo libero coordina le attività del Java User Group Sardegna. È laureato in Ingegneria Informatica presso il Politecnico di Torino ed è in possesso delle certificazioni SUN Certified Programmer for Java 2 e SUN Certified Web Component Developer for J2EE.

MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it