Introduzione allo strato web

Dopo aver analizzato il clustering di EJB nelle parti precedenti, concludiamo la serie esaminando lo strato web: load balancing HTTP e replicazione delle sessioni.

Load Balancing HTTP

Il load balancing distribui le richieste HTTP tra i vari nodi del cluster.

Tecniche di Load Balancing

Hardware Load Balancer

Dispositivi dedicati (F5, Cisco, etc.):

  • Performance elevate
  • Alta affidabilità
  • Costo elevato
  • Configurazione complessa

Software Load Balancer

Soluzioni software come modjk, modproxy:

  • Costo contenuto
  • Flessibilità
  • Performance buone
  • Configurazione semplice

DNS Round Robin

Tecnica basata su DNS:

  • Semplicissima
  • No single point of failure
  • Nessun controllo sullo stato dei nodi
  • Non consigliata per produzione

Configurazione Apache + mod_jk

Configurazione tipica per load balancing con Apache:

workers.properties

worker.list=loadbalancer,status

worker.node1.type=ajp13
worker.node1.host=server1
worker.node1.port=8009
worker.node1.lbfactor=1

worker.node2.type=ajp13
worker.node2.host=server2
worker.node2.port=8009
worker.node2.lbfactor=1

worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=node1,node2
worker.loadbalancer.sticky_session=1

httpd.conf

LoadModule jk_module modules/mod_jk.so
JkWorkersFile conf/workers.properties
JkLogFile logs/mod_jk.log
JkLogLevel info

<VirtualHost *:80>
    ServerName www.example.com
    JkMount /* loadbalancer
</VirtualHost>

Session Replication

Per garantire failover trasparente, le sessioni HTTP devono essere replicate.

Configurazione in JBoss

web.xml

<web-app>
    <distributable/>

    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
</web-app>

jboss-web.xml

<jboss-web>
    <replication-config>
        <replication-trigger>SET_AND_NON_PRIMITIVE_GET</replication-trigger>
        <replication-granularity>SESSION</replication-granularity>
        <use-jk>true</use-jk>
    </replication-config>
</jboss-web>

Modalità di replica

SESSION granularity

Replica l'intera sessione ad ogni modifica:

  • Semplice
  • Overhead di rete maggiore
  • Consigliata per sessioni piccole

ATTRIBUTE granularity

Replica solo gli attributi modificati:

  • Più efficiente
  • Complessità maggiore
  • Consigliata per sessioni grandi

FIELD granularity

Replica solo i campi modificati degli oggetti:

  • Massima efficienza
  • Complessità massima
  • Per casi specifici

Sticky Sessions

Le sticky session associano un client ad un nodo specifico:

worker.loadbalancer.sticky_session=1
worker.loadbalancer.sticky_session_force=0

Vantaggi

  • Riduce traffico di replica
  • Migliori performance
  • Uso ottimale cache locali

Svantaggi

  • Failover più complesso
  • Possibile sbilanciamento
  • Sessioni perse su restart

Best Practices per le sessioni

Minimizzare la dimensione

// Male: oggetti grandi in sessione
session.setAttribute("risultati", listaCompleta);

// Bene: solo riferimenti essenziali
session.setAttribute("risultatiId", idRisultati);

Usare oggetti serializzabili

public class CarrelloBean implements Serializable {
    private static final long serialVersionUID = 1L;
    private List<Prodotto> prodotti;
}

Configurare timeout appropriati

<session-config>
    <session-timeout>30</session-timeout>
</session-config>

Implementare session cleanup

@WebListener
public class SessionCleanupListener implements HttpSessionListener {
    public void sessionDestroyed(HttpSessionEvent event) {
        // Pulizia risorse
    }
}

Monitoring e troubleshooting

JMX MBeans

Per monitorare lo stato del cluster:

MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("jboss.web:type=Manager,*");
Set<ObjectInstance> instances = server.queryMBeans(name, null);

Log analysis

Analizzare i log per identificare problemi:

grep "Session replication" server.log
grep "Failover" server.log
grep "Load balancing" mod_jk.log

Testing del cluster web

Test di load balancing

Verificare la distribuzione delle richieste:

for i in {1..100}; do
    curl -s http://www.example.com/test.jsp | grep "Server:"
done | sort | uniq -c

Test di failover

Simulare guasto di un nodo:

1. Creare una sessione 2. Annotare sessionId 3. Fermare il nodo corrente 4. Verificare che la sessione persista

Test di session replication

Verificare la replica:

@WebServlet("/test-replication")
public class ReplicationTestServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        HttpSession session = req.getSession();
        Integer counter = (Integer)session.getAttribute("counter");
        counter = (counter == null) ? 1 : counter + 1;
        session.setAttribute("counter", counter);

        resp.getWriter().println("Counter: " + counter);
        resp.getWriter().println("Node: " + System.getProperty("jboss.node.name"));
    }
}

Conclusioni

Il clustering dello strato web completa l'architettura ad alta disponibilità. La combinazione di load balancing e session replication permette di costruire applicazioni scalabili e resilienti. È fondamentale testare accuratamente il comportamento del cluster, specialmente i scenari di failover.

Questa serie di tre articoli ha coperto tutti gli aspetti del clustering J2EE: dalla configurazione base, al clustering EJB, fino allo strato web. Con queste competenze è possibile progettare e implementare architetture enterprise robuste e scalabili.