Aggregatore Risorse Aggregatore Risorse

Indietro

Cluster a rombo

Un cluster può dirsi:

  • verticale, se più istanze della medesima applicazione sono in esecuzione all'interno dello stesso server fisico
  • orizzontale, se le istanze si trovano su server differenti

La licenza EE di Liferay è "per singolo server", ove per "server" si intende quel sistema, fisico o virtuale, dotato di scheda di rete, CPU e OS, con al massimo 8 core. E' quindi teoricamente possibile installare nel medesimo server 2 o 3 istanze di Liferay in cluster fra loro e con una sola licenza. Ad esempio, con 2 server di questo tipo, si potrebbe allestire un cluster a 6 nodi, attivandone 3 solamente in situazioni di alto carico.

La più semplice modalità di installazione Liferay in cluster è detta "a rombo", dal momento che coinvolge quattro server distinti:

  • almeno due Application Server (con Apache Tomcat)
  • un Web Server (con Apache HTTP Server) che agisce da load balancer e reverse proxy per i nodi del cluster
  • un Database Server

Nel caso il portale debba essere esporto in Internet, tutti i server del cluster saranno generalmente posti nella DMZ, compreso il server di database, che comunque conterrà gli stessi dati del portale pubblico. Tuttavia, il Reverse Proxy sarà l'unico ad essere realmente visibile in Internet, grazie alla presenza di due interfacce di rete, una con indirizzo IP pubblico e l'altra con indirizzo IP privato, chiaramente nella stessa subnet degli altri nodi. Eventualmente, comunque, anche questi potrebbero essere dotati di indirizzi pubblici, così da potervi accedere remotamente in caso di emergenza.

La tipologia di cluster a rombo soffre di due punti di rottura, cioè il Web Server e il Database Server. Infatti, in caso di guasto del Web Server, il portale sarà attivo ma irraggiungibile; al contrario, il guasto del Database Server causerà il crash di Liferay in entrambi i nodi. Il cluster a rombo, quindi, è abbastanza semplice da realizzare e consente di gestire un traffico considerevole, a costo di un elevato "ottimismo" sull'affidabilità dell'hardware.

Si descriveranno ora i passaggi necessari alla creazione di un cluster Liferay a rombo. Si prevede l'utilizzo delle seguente macchine:

  • lr6apache (IP 10.3.18.11): load balancer e reverse proxy
  • lr6tomcat1 (IP 10.3.18.21): primo nodo del cluster
  • lr6tomcat2 (IP 10.3.18.22): secondo nodo del cluster
  • lr6dbs1 (IP 10.3.18.31): database server

Attività su LR6TOMCAT1 #

Preparazione ambiente (come utente root) #

  • mkdir -p /w1/java/apps/INSTALL
  • mkdir -p /w1/java/liferay
  • Copiare in questa cartella i file jdk-6u21-linux-i586.bin, liferay.portal-6.0.5.war, liferay-portal-tunnel-web-6.0.5.war

Installazione JDK #

  • cd /w1/java/apps
  • bash ../INSTALL/jdk-6u21-linux-i586.bin

Creazione gruppo utenti e nuovo utente Liferay #

  • groupadd -g 321 javaapps
  • useradd -g 321 -d /w1/java/liferay/lrprod1 lrprod1
  • passwd lrprod1

Installazione Apache Tomcat #

  • cd /w1/java/apps
  • tar xzf ../INSTALL/apache-tomcat-6.0.26.tar.gz
  • cd apache-tomcat-6.0.26/webapps
  • rm -rf *

Creazione nuovo ambiente #

  • su - lrprod1
  • mkdir bin
  • mkdir config
  • mkdir portale
  • mkdir tmp
  • mkdir UPDATE

Creazione script #

  • cd bin
  • Creare lo script setenv, contenente le seguenti definizioni:
    export CATALINA_HOME=/w1/java/apps/apache-tomcat-6.0.26export CATALINA_BASE=$HOME/portale/tomcat-6.0.26export JAVA_HOME=/w1/java/apps/jdk1.6.0_21export PATH=$JAVA_HOME/bin:$PATHexport LPORTAL_TOMCAT=$CATALINA_BASE # necessario a lportal
  • Creare lo script lportal
  • Creare lo script setenv.javaopts: tale script sarà invocato da lportal e indicherà all'interno della variabile $JAVA_OPTS i parametri recepiti dalla JVM. Il file fornito include una serie di opzioni e di variabili locali necessarie all'attivazione di alcuni messaggi di diagnostica aggiuntivi:
    • Garbage Collection Debug: se abilitato, attiverà la creazione di un file in $CATALINA_BASE/tomcat/logs avente nel nome la data/ora di avvio della JVM e contenente tutti i dettagli relativi al Garbage Collector. Tale file potrà poi essere passato a un programma per l'analisi dello stato della memoria, ad esempio in modo da rilevare eventuali picchi di utilizzo
    • Heap Dump: se abilitato, e in caso di un errore di OutOfMemory, scatenerà la creazione di un dump della memoria al momento dell'errore. Il file sarà creato in /tmp, dal momento che potrà raggiungere dimensioni considerevoli (anche diversi GB) e potrà dunque essere escluso dai backup
    • -Xms e -Xmx: indicano rispettivamente la dimensione minima e massima dell'heap. In produzione, è opportuno che questi due valori siano uguali, così che la JVM possa allocare immediatamente tutta la RAM a sua disposizione
    • -XX:MaxPermSize: dimensione della Permanent Generation
  • chmod 750 *

Installazione portale #

  • Estrarre liferay-tomcat-base.tar.gz, andando così a creare la cartella $HOME/portale/tomcat-6.0.26, cioè la $CATALINA_BASE dell'ambiente. All'interno di tale cartella, fra le altre cose, sono presenti le informazioni di configurazione per Tomcat:
    • ROOT.xml, con l'attributo crossContext impostato a true. Questo file dovrebbe essere modificato nel caso in cui si decida di posizionare Liferay in un contesto diverso da ROOT (un'operazione non consigliata)
    • catalina.properties, contenente il riferimento alle librerie in $CATALINA_BASE/lib/ext
    • server.xml, che si assicura che tutto il traffico sia codificato in UTF-8, attivando inoltre la AccessLogValve in modalità "combined"
  • cd
  • ln -s portale/tomcat-6.0.26 tomcat
  • cd portale
  • Creare il file portal-ext.properties:
    include-and-override=${user.home}/config/portal-runtime.properties
  • cd tomcat-6.0.26/webapps
  • mkdir ROOT
  • unzip /w1/java/liferay-portal-6.0.5.war
  • cd
  • ln -s portale/deploy

Attività su LR6TOMCAT2 #

Preparazione ambiente (come utente root) #

  • mkdir -p /w1/java/apps/INSTALL
  • mkdir -p /w1/java/liferay
  • Copiare in questa cartella il file jdk-6u21-linux-i586.bin

Installazione JDK #

  • cd /w1/java/apps
  • bash ../INSTALL/jdk-6u21-linux-i586.bin

Creazione gruppo utenti e nuovo utente Liferay #

  • groupadd -g 321 javaapps
  • useradd -g 321 -d /w1/java/liferay/lrprod1 lrprod1
  • passwd lrprod1

Creazione nuovo ambiente #

  • su - lrprod1
  • Utilizzare
    rsync
    per copiare la cartella $HOME/bin e la cartella $HOME/portale dal primo nodo
  • Controllare i permessi delle cartelle sincronizzate, ad esempio verificando tramite il comando
    uid
    che gli UserID degli utenti owner siano gli stessi
  • cd
  • mkdir tmp

Attività su LR6DBS1 #

Come già esposto precedentemente, i DBMS principalmente utilizzati nelle installazioni di Liferay sono MySQL e PostgreSQL. Fra questi sistemi sono naturalmente presenti alcune differenze, una parte delle quali risulta essere di particolare importanza nelle installazioni Liferay.

In MySQL, innanzitutto, i permessi sono gestiti internamente dal DBMS, mentre PostgreSQL può demandare l'autenticazione degli utenti al Sistema Operativo: per questa ragione, agganciando il Sistema Operativo a un server LDAP, se il Sistema Operativo è agganciato a un server LDAP, allora anche l'autenticazione a un database PostgreSQL si baserà sui dati di tale server.

Un'altra differenza riguarda i nomi delle tabelle e dei campi, che nei database PostgreSQL sono sempre lower-case; al contrario, MySQL, in ambiente Linux, utilizza una sintassi case-sensitive. Questo aspetto è importante ad esempio nei casi di migrazione del database da Windows a Linux e viceversa.

Infine, in MySQL si dovrà configurare opportunamente la dimensione massima dei risultati delle query SQL, soprattutto nel caso in cui si sia deciso di memorizzare immagini o documenti all'interno del database: in questo caso, infatti, il file viene codificato in MIME Base64 e salvato in un campo TEXT (con un incremento della dimensione da 1 MB a 1,4 MB, ad esempio). Di norma, quindi, si preferisce impostare una dimensione massima dei risultati SQL pari ad almeno 64 MB.

Nelle installazioni cluster di Liferay, è inoltre necessario prestare attenzione a un altro dettaglio, riguardante il numero massimo di connessioni gestibili dal DBMS adottato. Infatti, sia PostgreSQL che MySQL consentono di default un massimo di 100 connessioni contemporanee. Liferay, come già illustrato precedentemente, è configurato per gestire un pool di 100 connessioni. Si dovrà dunque fare in modo che il numero massimo di connessioni consentito dal DBMS sia almeno pari alla somma delle dimensioni dei pool dei vari nodi del cluster.

Nelle istruzioni che seguono, si procederà alla configurazione di PostgreSQL nel server LR6DBS1:

Configurazione di PostgreSQL #

  • chkconfig postgresql on
  • cd /var/lib/pgsql/data
  • Modificare il file pg_hba.conf, impostando "md5" per l'accesso locale tramite IPv4 e IPv6 e aggiungendo la seguente riga:
    host    all    all    10.3.18.0/24    md5
    (ove 10.3.18.0/24 è la sottorete dei server)
  • Modificare il file postgresql.conf, attivando la funzione di "autovacuum" e impostando
    listen_addresses="*"
  • /etc/init.d/postgresql restart

Creazione del tablespace #

  • cd /w1/database/liferay/lrprod
    (ovvero il tablespace che conterrà il database di Liferay)
  • chown postgres:postgres .
  • su - postgres
  • psql
  • create tablespace lrprod location '/w1/database/liferay/lrprod';

Creazione del database Liferay #

  • create user lrprod1 createdb password 'lrprod1';
    (createdb è il ruolo del nuovo utente)
  • create database lrprod1 owner lrprod1 encoding 'UTF-8' tablespace lrprod;
  • \q

Parte di questi passaggi si rendono necessari al fine di impostare una posizione più opportuna per il tablespace rispetto a quella di default: infatti, sia PostgreSQL che MySQL posizionano di default i dati in /var/lib, che in genere non è molto capiente. Al contrario, è preferibile creare il tablespace in in un altro disco o partizione.

Attività su LR6TOMCAT1 e LR6TOMCAT2 #

Una volta installato e configurato opportunamente il DBMS, è necessario verificare che sia possibile accedervi dai due Application Server. Per fare ciò, è sufficiente eseguire il seguente comando dalla shell di uno dei due nodi del cluster:

psql -U lrprod1 -h 10.3.18.31 lrprod1

Una volta effettuata tale verifica, si potrà modificare il file portal-runtime.properties, inserendo l'indirizzo IP e la porta del server di database, nonché le credenziali per accedere al database. Si procederà quindi al riavvio del portale e al controllo del corretto funzionamento del sistema.

Una volta verificato il corretto funzionamento del primo nodo, si potrà quindi allineare anche LR6TOMCAT2, svuotando le cartelle logs, temp e work, e sincronizzando le cartelle bin e portale tramite

rsync
.

Si può ora procedere alla creazione del cluster, un'operazione che richiede l'inserimento di alcune opzioni all'interno del file portal-runtime.properties: infatti, per ciascuna criticità (database, cache, indici di ricerca e Document Library), Liferay propone una o più alternative in ambito cluster, ed è quindi necessario effettuare tali modifiche direttamente in Liferay, per far sì che le varie istanze siano il più possibile sincronizzate fra loro. Tuttavia, ciò non è sufficiente: infatti, le richieste dei client transitano prima dall'Application Server, ed è questo a preoccuparsi di creare e mantenere le sessioni, poi popolate da Liferay. Per mantenere la sincronizzazione completa fra i vari nodi, e fare così in modo che i dati degli utenti siano mantenuti validi anche nel caso di crash di parte del cluster (ad esempio, evitando all'utente la necessità di rieffettuare il login al portale), è possibile attivare un meccanismo di replica delle sessioni. Se un nodo va in crash, un altro potrà prendersi in carico la sessione in modo del tutto trasparente all'utente.

Per abilitare la replica delle sessioni, è necessario effettuare una serie di modifiche ai file di configurazione di Tomcat (presenti in $HOME/portale/tomcat/conf):

  • Modificare il file server.xml:
  • Dare un nome a ogni nodo del cluster, compilando l'attributo
    jvmRoute
    dell'elemento
    <engine>
    (ad esempio: "nodo1")
  • decommentare la riga sottostante, cioè:
    <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
  • Modificare il file web.xml:
    • Aggiungere l'elemento
      <distributable />
      come primo elemento figlio dell'elemento root
      <web-app>
      . In alternativa, è possibile aggiungere questo elemento all'interno del file $HOME/portale/tomcat/conf/Catalina/localhost/ROOT.xml

Comunque, la presenza delle Sticky Sessions (cioè la gestione delle varie richieste di un utente ad opera sempre dello stesso nodo) e del meccanismo di Session Failover è assolutamente opzionale. Infatti, per disabilitare il Session Failover, è sufficiente:

  • eliminare l'elemento
    <distributable />
    in web.xml
  • eliminare l'elemento
    <Cluster>
    in server.xml

Le modifiche al file portal-runtime.properties necessarie all'abilitazione del cluster possono essere invece così riassunte:

  • Per cache Hibernate, specifica:
    net.sf.ehcache.configurationResourceName=/ehcache/hibernate-clustered.xml
  • Per cache POJO, specifica:
    ehcache.multi.vm.config.location=/ehcache/liferay-multi-vm.clustered.xml
  • Per la sincronizzazione degli indici Lucene, specifica:
    lucene.replicate.write=truecluster.link.enabled=true
  • Il portale ha anche attività schedulate, e lo schedulatore si basa sulla libreria Quartz. In cluster, è necessario fare in modo che tutti i nodi avviino le attività schedulate indipendentemente. Per fare ciò, è necessario specificare:
    org.quartz.jobStore.isClustered=true
  • Per attivare JackRabbit nella Document Library, specifica:
    dl.hook.impl=com.liferay.documentlibrary.util.JCRHook
  • Liferay consente il salvataggio delle immagini nel file system, in una tabella del database o nel sistema indicato come gestore della Document Library. In questo esempio, si preferisce salvare le immagini nel database, perciò è necessario specificare:
    image.hook.impl=com.liferay.portal.image.DatabaseHook
  • In cluster, le varie istanze di Liferay comunicano tra loro tramite multicast. Nella sezione Multicast del file portal.properties sono presenti alcune opzioni relative a questo aspetto, come l'indirizzo e la porta multicast. La modifica di tali impostazioni potrebbe rendersi necessaria in alcuni scenari, ad esempio nel caso in cui siano presenti più cluster Liferay nella stessa rete

Nel caso in cui si utilizzi Jackrabbit per la Document Library e l'Image Gallery, il file contenente le impostazioni a cui il sistema farà riferimento è $HOME/portale/data/jackrabbit/repository.xml. L'impostazione di default presente in tale file indica a Jackrabbit di salvare i file nel file system locale, ma, se necessario, è possibile utilizzare come storage una SAN. In realtà, in questo esempio si preferisce configurare Jackrabbit affinché memorizzi i file in un database: per fare questo, è necessario de-commentare le porzioni del file repository.xml relative all'accesso al database, commentando invece le opzioni di default. Dal momento che uno degli obiettivi delle procedure di backup consiste nella creazione di backup consistenti, è opportuno configurare Jackrabbit affinché salvi i file direttamente all'interno del database di Liferay. Ciò non è un problema, dal momento che tutte le tabelle di Jackrabbit avranno prefisso "J_R_FS_"; inoltre, tutti i più diffusi DBMS consentono di partizionare il database, spostando alcune tabelle in altri database.

Jackrabbit crea un'area di lavoro, al cui interno posizionerà i file, i metadati sui file e le versioni successive dei file. In tal senso, sono disponibili due differenti meccanismi:

  • SimplePersistence: sono salvati i delta dei file con un metodo ottimizzato alle prestazioni, non all'occupazione su disco
  • StorageDbPersistence: i file sono salvati a blocchi, con un metodo ottimizzato all'occupazione su disco

Attivando il portale in un nodo, si noterà come JGroups (utilizzato anche da Ehcache) vada alla ricerca dell'indirizzo IP pubblico, e che, per far questo, cerchi di raggiungere www.google.com. Nel caso in cui i server non abbiano accesso a Internet (ad esempio, a causa della mancata configurazione del server proxy), sarà necessario indicare in portal-runtime.properties un host pubblico sicuramente raggiungibile, ad esempio:

cluster.link.autodetect.address=www.smc.it:80

Oltre a questo, potrebbero inoltre comparire altri errori, dovuti al fatto che la JDK 1.6u23 utilizza di default lo stack IPv6. Per risolvere questi problemi, è necessario modificare il file setenv.javaopts, impostando a

true
la voce "java.net.preferIPv4Stack" nella variabile $JAVA_OPTS.

In fase di test, può essere utile impostare in portal-runtime.properties la voce "web.server.display.node" a

true
: così facendo, nella parte inferiore di ogni pagina sarà visualizzato l'hostname del nodo che sta fornendo la richiesta.

Infine, si può effettuare una nuova sincronizzazione del secondo nodo e procedere all'avvio dell'intero cluster. Per verificare che il sistema stia effettivamente girando in modalità cluster, è possibile effettuare alcuni test:

  • aggiungere un portlet alla pagina, ad esempio il portlet Image Gallery, utilizzandolo quindi per inserire un'immagine: in questo modo, si potrà verificare che il database sia effettivamente centralizzato e che la replica della cache funzioni; per verificare che le immagini siano effettivamente salvate nel database, basterà assicurarsi che la cartella data/images non esista in nessun nodo del cluster
  • aggiungere il portlet Document Library e provare ad inserire un nuovo documento, così da verificare il corretto funzionamento di Jackrabbit
  • aggiungere il portlet Search ed effettuare una ricerca, così da verificare il corretto funzionamento di Lucene

Ora, avviando il portale nei vari nodi del cluster, è possibile notare una serie di nuovi messaggi, fra cui:

  • cluster mcast soTimeout to 500
    : significa che, se Tomcat non riceve risposta da un altro nodo entro 500 ms, lo considera come non disponibile; in situazioni ad altro traffico, questo valore di timeout potrebbe essere insufficiente
  • Sleeping form 1000 milliseconds to establish cluster membership
    : significa che Liferay attenderù 1000 ms prima di cercare altri nodi e sincronizzarsi con questi; è consigliabile utilizzare un valore pari ad almeno 5000 ms, in modo da limitare un passaggio di dati troppo prematuro, a nodi del cluster ancora in fase di avvio

E' necessario tenere presente che, per installare un portlet in un cluster, è necessario prima installarlo in un nodo, attendere il completamente dell'installazione, installarlo sull'altro nodo, attendere e così via. Infatti, il deployment di un portlet potrebbe causare l'aggiornamento del database di Liferay, ed è quindi necessario procedere in modo tale da evitare modifiche concorrenti.

Come detto, nel file server.xml devono essere elencate le Log Valve, fra cui la AccessLogValve. Nel caso in cui la stessa istanza di Liferay debba gestire più portali (quindi tramite Virtual Host), è necessario configurare l'AccessLogValve in modo tale che mostri nel campo referrer lo specifico Virtual Host a cui si indirizzava ogni richiesta:

<Valve   className="org.apache.catalina.valves.AccessLogValve"    directory="logs"    pattern='%h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" "%{Host}i"'    prefix="localhost_access_log."    suffix=".txt" resolveHosts="false"/>

Una modifica simile deve essere effettuata anche per il log di Apache. Queste informazioni sono utili ai fini di diagnostica tramite tool automatici come AWStats. Al contrario, Google Analytics è in grado di analizzare unicamente il traffico "umano", effettuato cioè da dispositivi in grado di eseguire codice Javascript. Non è questo il caso dei motori di ricerca, e infatti, soprattutto in ambito SEO, potrebbe essere utile analizzare il comportamento dei crawler; ad esempio, si è visto che recentemente Googlebot comincia ad annunciarsi anche come client WAP, e questo suggerisce di prestare attenzione anche ai temi e ai layout template per WAP.

Attività su LR6APACHE1 #

A livello di reverse proxy, è possibile decidere la politica di distribuzione delle richieste:

  • suddividere in modo equo le richieste fra i vari nodi del cluster; in tal caso, risulta fondamentale la replica delle sessioni
  • utilizzare il meccanismo delle "sticky sessions": una volta che un utente ha effettuato una richiesta, gli sarà restituito un cookie che lo identifica, in modo tale che le richieste successive siano sempre servite dallo stesso nodo. E' l'impostazione consigliata.

In ambienti con un alto numero di richieste, è consigliabile utilizzare le "sticky sessions" e disabilitare la replica delle sessioni. Infatti, tale funzione dovrebbe essere abilitata solo se espressamente richiesto; in tal caso, quindi, nel momento in cui il nodo che serviva un utente va in crash, questo dovrà effettuare nuovamente il login. Ad ogni modo, le sessioni non entrano in gioco solamente con gli utenti normali, ma anche con gli utenti anonimi, ad esempio con i motori di ricerca.

I passi necessari ad abilitare il reverse proxy in LR6APACHE1 possono dunque essere così riassunti:

  • yum install httpd
  • chkconfig httpd on
  • cd /etc/httpd/conf.d
  • Modificare proxy_ajp.conf, inserendo le seguenti impostazioni:
    <Location /balancer-manager>    SetHandler balancer-manager

Order deny,allow Deny from all Allow from 10.1.1.3</Location>

  1. Indico i percorsi non coinvolti nel proxy (pagine statiche servite direttamente da Apache o da applicazione php, perl, ecc.)ProxyPass /server-status !ProxyPass /balancer-manager !
  1. Definisco il cluster<Proxy balancer://corso> BalancerManager ajp://10.3.18.21:8009 route=nodo1 BalancerManager ajp://10.3.18.22:8009 route=nodo2</Proxy>
  1. Dico che voglio le Sticky Session e il failover delle sessioniProxyPass / balancer://corso/ stickysession=JSESSIONID nofailover=off
  1. Serve a togliere qualsiasi riferimento agli indirizzi IP dei nodi singoli, trasformandoli in '/'ProxyPassReverse / ajp://10.3.18.21:8009ProxyPassReverse / ajp://10.3.18.22:80095. Modificare httpd.conf, inserendo le seguenti impostazioni:ExtendedStatus On

<Location /server-status> SetHandler server-status Order deny,allow Deny from all Allow from 10.1.1.3</Location>}}}

  • Disattivare il firewall:
    /etc/init.d/iptables stop
  • Riavviare Apache

Il modulo AJP (mod_proxy_ajp), installato di default in CentOS e da installare in SUSE, consente di fare reverse proxy su Tomcat. Oltre a questo, è disponibile anche il modulo mod_jk, tramite il quale è possibile effettuare reverse proxy anche con servizi di altro tipo.

Apache mette a disposizione due interfacce di amministrazione, aventi lo scopo di gestire rispettivamente il Web Server e i vari nodi del cluster. La prima interfaccia, raggiungibile all'indirizzo /server-status, presenta una serie di informazioni, che possono essere eventualmente collezionate in un file .xml storicizzabile secondo politica round-robin. Ad esempio, la voce "Parent Server Generation" riguarda il processo di distruzione e nuova creazione del processo di Apache e dei singoli worker dopo un numero prestabilito di richieste, un'attività effettuata allo scopo di mitigare gli effetti degli eventuali memory leak.

L'altra interfaccia di amministrazione, invece, è raggiungibile all'indirizzo /balance-manager e consente di visualizzare la situazione del Load Balancer e dei singoli nodi del cluster. La voce "byrequests" indica l'algoritmo di scelta del nodo.