sabato, Novembre 23, 2024

Apache + Tomcat + Load Balancing

Giovanni "Jinko" Uccio
Giovanni "Jinko" Ucciohttps://ie.linkedin.com/in/giovanniuccio
- Software Engineer - Debian Evangelist - Escalation Engineer - Debianizzati.org

Introduzione

In questo articolo (ove sarò molto diretto a spicciolo) andremo ad illustrare una configurazione / monitoring di più di nodi tomcat, in dialogo con un jk connector verso un server apache che sfruttando questa connessione metterà in atto il Load balancing.
Baseremo tutta la pratica su dei server equipaggiati con la  distribuzione Linux CentOS 5.5, tutta questa pratica (giusto per la cronaca) è stata sviluppata e messa in deploy su un ambiente VMware ESXi.

Sommario

  • Descrizione contesto
  • Caratteristiche implementate
  • Configurazione nodo Apache Tomcat
  • Definizione workers.properties
  • Status Worker
  • Configurazione Apache Web Server

Descrizione contesto

Server Apache:

OS: CentOS 5.5
IP: 172.22.9.42
Apache web server: 2.2.3
mod_jk: 1.2.27

Server Tomcat1:

OS: CentOS 5.5
IP: 172.22.9.40
Apache Tomcat: 6.0.26

Server Tomcat 2:

OS: CentOS 5.5
IP: 172.22.9.41
Apache Tomcat: 6.0.26

Caratteristiche implementate

  • Balacing
  • Failover
  • Hot Standby (viene solo mostrata)
  • Socket timeout
  • Error state check
  • JK Status (monitoring)

Configurazione nodo Apache Tomcat

Definiamo una porta univoca ove il jk connector potrà connettersi verso questo nodo tomcat:

<Connector port="8008" protocol="AJP/1.3" redirectPort="8443" />

Bisognerà poi andare a definire una jvmRoute univoca che avrà il nome del worker definito nella nostra worker.list. essa servirà all’interno del gruppo di nodi designati per il  load balancing. Il nome viene legato alla generazione di una sessione in modo da far reindirizzare questa sessione sempre allo stesso nodo :

<Engine name="Catalina" defaultHost="localhost" jvmRoute="worker1">

Definizione file workers.properties

path: /etc/httpd/conf/workers.properties

nano workers.properties, e inseriamo il seguente codice:

ps=/

# The advanced router LB worker

worker.list=load_balancer, worker1,worker2

# Controlliamo ogni ora se un balancer è in stato di errore

worker.maintain=3600

# Definiamo un worker usando ajp13 per il nodo tomcat1

worker.worker1.port=8008
worker.worker1.host=172.22.9.40

# Il tipo ajp13 è utilizzato poichè il JK connector lo utilizza per la comunicazione tra il web server e il tomcat

worker.worker1.type=ajp13

# lbfactor setta quanto un worker debba lavorare rispetto ad un altro,
# ed è comparato con i valori degli altri workers attivi

worker.worker1.lbfactor=100

# Definiamo il nodo di failover preferito per il worker1

worker.worker1.redirect=worker2

# Definiamo un worker usando ajp13 per il nodo tomcat1
# porta definita sulla quale il tomcat è in ascolto per le richieste JK

worker.worker2.port=8009
worker.worker2.host=172.22.9.41
worker.worker2.type=ajp13

# lbfactor setta quanto un worker debba lavorare rispetto ad un altro,
# ed è comparato con i valori degli altri workers attivi
worker.worker2.lbfactor=100

# Questa opzione (chiamata HOT STANDBY) non la useremo, ma la inserisco commentata nel caso vi dovesse servire. Nello specifico server a: “Disabilita il worker per tutte le richieste, eccetto per il failvoer. Questo significa che esso riceve richieste nel caso in cui il worker che lo ha designato come failover node andasse in errore.

#worker.worker2.activation=disabled

# Definiamo il nodo di failover preferito per il worker2

worker.worker2.redirect=worker1

# timeout del socket (espresso in secondi) che viene utilizzato per la comunicazione tra il modulo Jk e l’host remoto. Se quest’ultimo non dovesse rispondere entro il lasso dei tempo di timeout impostato Il Jk produrrà un errore e proverà di nuovo. Lasciando il valore a zero il Jk aspetterà per un tempo infinito su tutte le operazioni del socket.

worker.worker2.socket_timeout=3600

Prima di andare a spiegare le prossime due righe volemo precisare questa cosa (dato che in questo articolo sto dando una conoscenza di base della tematica che si è affrontata): ”

Il load balancer è un worker virtuale ma si occupa dell’interazione/gestione dei worker che gli vengono associati e definiti come reali, questo significa che di fatto esso non “realmente” con essi. In ultimo un worker viene definito load balancer quando il type assume il valore “lb”

# definiamo alcuni parametri per il load balancer, come il tipo in questo caso tipo e l’errore da restituire in caso di fault.

worker.load_balancer.type=lb
worker.load_balancer.fail_on_status=404

# Tipologie di load balancing: #

Attraverso la direttiva “worker.load_balancer.method=value” andiamo a definire il metodo con il quale viene selezionato il miglior worker verso il quale dovrà essere inoltrata la nostra richiesta. Andiamo ad identificare i valori possibili e a darne una spiegazione:

R[quest]: il balancer userà il numero delle richieste accodate su ogni worker per determinare il migliore da servire. Gli accessi vengono distrbuiiti secondo l’ lbfactor secondo il criterio del “windows sliding time”. Questo valore è quello di default.

S[ession]: il balancer userebbe il numero di sessioni per cercare il miglior worker….gli accessi sarebbero comunque distribuiti secondo il “window sliding time” poichè il balancer non mantiene nessuna informazioni sullo stato (stateless) e attualmente non ha visione/conoscenza del numero di sessioni. Invece viene effettuato un conteggio su ogni richiesta senza “cookie sessio” o “URL encoding” che viene quindi calcolata essere una nuova sessione. Viene consigliato di utilizzare questo valore quando le sessioni
sono la risorsa limitante.

T[raffic]: il balancer utilizzerà il traffico di rete tra il server JK e il server tomcat per definire il miglio worker. Gli accessi saranno distribuiti in accordo con l’ lbfactor in una “window sliding time” Questo metodo dovrebbe essere utilizzato se la rete da/verso i backends costituiscono la risorsa limitante.

B[usyness]: il balancer selezionerà il worker con il carico di lavoro corrente più basso, questa tecnica è basata su quante richieste il worker sta servendo correntemente. Il numero viene diviso per l’ lbfactor di tutti gli altri worker e il valore più basso (che praticamente corrisponde a quello meno occupato) viene scelto come worker a cui inoltrare la richiesta.
Questo metodo risulta interessante nel momento in cui la richesta richiede un tempo lungo per essere processato, per esempio un corposo download.

# Definiamo che tipologia di load balancing decidiamo di utilizzare

# default vaule = R quindi non lo setto
#worker.load_balancer.method=R

# Definiamo i workers da utilizzare

worker.load_balancer.balance_workers=worker1, worker2

Trattiamo adesso la parte del worker che ci server per effettuare il monitoring dello stato dei nostri JK connectors:

Status Worker Reference

Esiste un particolare tipo di worker chiamato “status worker”, esso non ha il compito di girare le richieste alel istance dei nodi tomcat ma di reperire le informazioni di gestione, stato, configurazione in runtime e cambiare nel caso delel configurazioni in modo dinamico; tutto attraverso una interfaccia web integrata (molto semplice e snella).

Nellìesempio sottostante ho configurato due tipo di worker status, uno che consente le modifiche e azioni di gestione da parte di un prsunto sysadmin, e il secondo una semplice versione dello stesso in modalità read-only per un eventuale monitoring da parte – la butto li – di una persona addetta alla segnalazione di errori.
Andrmeo poi a vedere come nella configurazione si apache renderemo queste “location” disponibili ad un solo pre-determinato indirizzo ip e negando l’accesso a tutti gli altri.

# Aggiungiamo questo particolare worker alla lista (questo sarà quello per l’admin)

worker.list=jkstatus

# definiamo il jkstatus
worker.jkstatus.type=status

# definiamo il punto di mount
worker.jkstatus.mount=/private/jkmanager

# un altro worker ti questa tipologia ma solo read-only
worker.list=jkview
worker.jkview.type=status
worker.jkview.read_only=True
worker.jkview.mount=/private/jkview

Configurazione Apache web Server

Andiamo un secondo a vedere come rendere accessibili questi worker i lavori tramite apache, andiamo a modificare il file httpd.conf, e inseriamo le seguenti righe alla fine del file:

# Worker properties file
JkWorkersFile /etc/httpd/conf/workers.properties

# Logging
JkLogFile /var/log/httpd/mod_jk.log

# Set the jk log level [debug/error/info]
JkLogLevel debug

# Log Format
JkLogStampFormat " [%a %b %d %H:%M:&S %Y] "

# Send servlet for context / AGO_EXT to worker named worker1

JkMount /WEAPP1 load_balancer
JkMount /WEBAPP1/* load_balancer

JkMount /WEBAPP2 load_balancer
JkMount /WEBAPP2/* load_balancer
<Location /private/jkmanager> JkMount jkstatus Order Deny,Allow Deny from all Allow from 172.22.80.12 </Location>
 <Location /private/jkmonitor> JkMount jkview Order Deny, Allow Deny from all Allow from 172.22.50.36 </Location> 

Per la parte relativa al semplice tomcat con mod_jk potete anche dare un occhio a questo articolo

Infine vi propongo una schermata di come è il jkmanager e per gli approfondimenti vi rimando alla documentazione ufficiale del sito tomcat.apache.org perchè come sempre questo è solo un assaggio per stuzzicare la mente :)



Un saluto,

Giovanni Uccio

Articoli correlati

Noleggia una Tesla per il tuo evento ICT!

Categorie