Il load balancing è una tecnologia fondamentale nelle infrastrutture IT moderne quando un singolo server non è più sufficiente per gestire in modo affidabile il traffico generato da utenti, applicazioni e servizi. In una configurazione tradizionale, un'applicazione web o un servizio aziendale può essere ospitato su un unico server che riceve direttamente tutte le richieste. Questa architettura può funzionare correttamente quando il numero di connessioni è limitato, ma con la crescita del traffico aumenta anche il carico su CPU, RAM, storage e rete, fino a raggiungere il limite operativo del sistema. In questo scenario il server diventa contemporaneamente un collo di bottiglia e un single point of failure, perché un suo malfunzionamento può rendere indisponibile l'intero servizio. Il load balancing permette di superare questa limitazione introducendo un livello intermedio che riceve le richieste dei client e le distribuisce tra più server backend, creando un'infrastruttura nella quale il carico può essere ripartito e la disponibilità del servizio può essere mantenuta anche in presenza di problemi su uno dei nodi.

Come funziona il load balancing

Dal punto di vista dell'utente, un'infrastruttura con load balancing può apparire esattamente come un normale servizio accessibile attraverso un unico dominio. Quando il browser o un'applicazione effettua una richiesta verso il servizio, la connessione viene ricevuta dal load balancer, che analizza la richiesta e determina quale server backend dovrà elaborarla. I server applicativi si trovano quindi dietro il sistema di bilanciamento e non devono necessariamente essere esposti direttamente su Internet. Questo modello consente di aggiungere più nodi mantenendo invariato l'endpoint utilizzato dagli utenti e permette al load balancer di controllare dinamicamente quali sistemi possono ricevere traffico.

Il funzionamento diventa particolarmente importante quando l'applicazione deve gestire un numero elevato di richieste contemporanee. Invece di concentrare tutto il carico su un singolo server, le connessioni vengono distribuite tra più sistemi. Se, ad esempio, un'applicazione viene eseguita su tre server identici, il load balancer può distribuire le richieste tra i tre nodi secondo una determinata logica. L'obiettivo non è necessariamente dividere matematicamente il traffico in parti uguali, ma utilizzare le risorse disponibili nel modo più efficace possibile tenendo conto dello stato dei server, del numero di connessioni e delle caratteristiche dell'applicazione.

Layer 4 e Layer 7

Dal punto di vista tecnico, una delle principali differenze riguarda il livello sul quale viene effettuato il bilanciamento. Un load balancer Layer 4 opera principalmente a livello di trasporto e utilizza informazioni relative a protocolli come TCP e UDP, porte e indirizzi IP. In questo caso il sistema può distribuire le connessioni senza dover necessariamente interpretare il contenuto applicativo della richiesta. Questo approccio è particolarmente utile quando sono richieste elevate prestazioni o quando il traffico non è esclusivamente HTTP.

Un load balancer Layer 7 lavora invece a livello applicativo e può comprendere il protocollo HTTP. Questa caratteristica permette di prendere decisioni molto più precise sulla destinazione della richiesta. Il sistema può, ad esempio, analizzare il dominio richiesto, il percorso URL, gli header HTTP o determinati cookie e decidere quale backend utilizzare. Un'applicazione potrebbe quindi avere un gruppo di server dedicato alle API e un altro dedicato alla parte web, mentre il load balancer determina automaticamente la destinazione in base al contenuto della richiesta. La scelta tra Layer 4 e Layer 7 deve essere effettuata in funzione dell'architettura applicativa e del livello di controllo richiesto, perché le due modalità risolvono esigenze differenti.

Algoritmi per distribuire le richieste

Il load balancer deve utilizzare un criterio per determinare quale server riceverà una nuova richiesta. Uno degli algoritmi più conosciuti è il Round Robin, che distribuisce le richieste in sequenza tra i server disponibili. Questo sistema è semplice e funziona bene quando i backend hanno caratteristiche hardware simili e gestiscono richieste con un costo computazionale comparabile. Quando invece i server hanno capacità differenti può essere utilizzato un sistema Weighted Round Robin, nel quale ogni nodo riceve un peso e il traffico viene distribuito tenendo conto della capacità relativa dei sistemi.

Un'altra modalità molto utilizzata è il Least Connections, che considera il numero di connessioni attive su ciascun backend e tende a indirizzare la nuova connessione verso il server che presenta il numero inferiore di connessioni. Questo può risultare particolarmente utile quando le richieste hanno durate differenti e una semplice distribuzione sequenziale non rappresenta correttamente il carico reale. Esistono inoltre algoritmi basati su hash dell'indirizzo IP, cookie o altri parametri, utilizzati quando è necessario mantenere una certa persistenza tra client e server.

Health check e controllo dello stato dei server

La distribuzione del traffico può funzionare correttamente solo se il load balancer conosce lo stato dei server backend. Per questo motivo vengono utilizzati gli health check, cioè controlli periodici che verificano se un determinato nodo è effettivamente disponibile. Un controllo molto semplice può verificare che una porta TCP sia raggiungibile, mentre un controllo applicativo può effettuare una richiesta HTTP verso un endpoint specifico e verificare il codice di risposta.

Questa differenza è importante perché un server può essere raggiungibile a livello di rete ma avere l'applicazione non funzionante. Un web server potrebbe continuare ad accettare connessioni mentre il processo applicativo, il database o una componente fondamentale del servizio non risponde correttamente. Un health check progettato in modo adeguato permette quindi di valutare lo stato effettivo del servizio e non soltanto quello dell'hardware o della rete. Quando un backend non supera i controlli configurati, il load balancer può rimuoverlo temporaneamente dal pool e smettere di inviargli nuove richieste. Quando il sistema torna operativo, il nodo può essere reinserito automaticamente.

Reverse proxy e terminazione TLS

Molti load balancer moderni funzionano anche come reverse proxy. In questa configurazione il client non comunica direttamente con il server applicativo, ma stabilisce la connessione con il reverse proxy, che successivamente inoltra la richiesta al backend. Questa architettura permette di centralizzare diverse funzioni infrastrutturali e di mantenere i server applicativi separati dalla rete pubblica.

Il reverse proxy può anche occuparsi della terminazione TLS. In questo caso il client stabilisce una connessione HTTPS con il load balancer, che gestisce il certificato digitale e la cifratura. Il traffico può quindi essere inoltrato verso il backend attraverso HTTP oppure attraverso una seconda connessione HTTPS, in base ai requisiti di sicurezza dell'infrastruttura. La gestione centralizzata dei certificati può semplificare notevolmente l'amministrazione quando sono presenti numerosi server, anche se negli ambienti che richiedono una protezione elevata è spesso opportuno mantenere la cifratura anche nella comunicazione tra load balancer e backend.

Sessioni applicative e applicazioni stateless

Uno degli aspetti più delicati riguarda la gestione delle sessioni. Se un'applicazione memorizza lo stato della sessione direttamente sul filesystem del server, un utente che effettua il login sul server A potrebbe trovarsi successivamente collegato al server B, che non dispone della stessa sessione. Questo può causare disconnessioni, perdita dello stato dell'utente o comportamenti anomali.

Una soluzione consiste nell'utilizzo delle sticky session, attraverso le quali il load balancer cerca di mantenere lo stesso client associato allo stesso backend. Questa tecnica può essere efficace in determinati contesti, ma crea una dipendenza maggiore dal singolo server. Se il nodo viene arrestato, la sessione può andare persa.

Un'architettura più moderna consiste nel progettare applicazioni stateless, nelle quali lo stato necessario non viene mantenuto esclusivamente sul server che elabora la richiesta. Le informazioni di sessione possono essere gestite attraverso database o sistemi di caching e storage condivisi. In questo modo qualsiasi nodo disponibile può elaborare una richiesta e l'aggiunta di nuovi server diventa più semplice. Questo principio è particolarmente importante nelle applicazioni progettate per la scalabilità orizzontale e negli ambienti cloud.

Load balancing e alta disponibilità

Il load balancing viene spesso associato all'alta disponibilità, ma le due funzioni non sono esattamente la stessa cosa. Il load balancer distribuisce il traffico, mentre l'alta disponibilità richiede che l'architettura continui a funzionare anche quando uno o più componenti diventano indisponibili. Per ottenere questo risultato è necessario evitare che il load balancer stesso rappresenti un single point of failure.

Se un'infrastruttura dispone di cinque server applicativi ma utilizza un unico load balancer fisico, il guasto del bilanciatore può rendere irraggiungibili tutti i backend. In un ambiente critico è quindi necessario prevedere ridondanza anche a questo livello, utilizzando sistemi in alta disponibilità o servizi distribuiti. Lo stesso ragionamento deve essere applicato agli switch, ai firewall, ai collegamenti di rete, all'alimentazione e allo storage. L'obiettivo non è semplicemente avere più server, ma eliminare progressivamente i punti singoli di guasto lungo tutto il percorso che una richiesta deve attraversare.

Load balancing e database

Un errore frequente consiste nel pensare che, aumentando il numero dei web server, l'intera applicazione diventi automaticamente scalabile. Il livello applicativo può essere distribuito su più nodi mentre il database rimane concentrato su un singolo server. In questo caso il database può diventare il nuovo collo di bottiglia.

Quando il carico aumenta, è quindi necessario analizzare anche la componente dati. In base alla tecnologia utilizzata possono essere introdotte repliche, read replica, clustering o altre architetture distribuite. È importante distinguere le operazioni di lettura da quelle di scrittura perché non tutte le richieste possono essere trattate allo stesso modo. Una replica utilizzata per le letture può avere un ritardo rispetto al database primario e questo deve essere considerato dall'applicazione quando è richiesta una consistenza immediata.

Il load balancing deve quindi essere progettato insieme all'architettura del database. Distribuire correttamente le richieste HTTP non risolve il problema se tutte le istanze applicative continuano a generare un numero eccessivo di query verso un unico database.

Load balancing nelle API e nei servizi moderni

Le API rappresentano uno degli scenari nei quali il load balancing viene utilizzato maggiormente. Un'applicazione mobile, un gestionale o un servizio esterno può inviare richieste verso un unico endpoint API mentre dietro di esso sono presenti numerose istanze applicative.

Il load balancer può distribuire le richieste, controllare la disponibilità delle istanze e raccogliere informazioni sulle prestazioni. In architetture più complesse può inoltre essere affiancato da un API gateway, che gestisce autenticazione, autorizzazione, rate limiting, logging e altre funzioni specifiche del traffico API.

Quando l'applicazione è composta da microservizi, la gestione del traffico diventa ancora più complessa perché ogni servizio può avere più istanze e può essere necessario utilizzare meccanismi di service discovery per individuare dinamicamente i nodi disponibili. In questi ambienti il bilanciamento deve quindi adattarsi continuamente alle variazioni dell'infrastruttura.

Load balancing e scalabilità orizzontale

Uno dei principali vantaggi del load balancing è la possibilità di utilizzare la scalabilità orizzontale. Invece di aumentare continuamente le risorse di un unico server, è possibile aggiungere nuovi nodi e distribuire il traffico tra tutti i sistemi disponibili.

Questo modello è particolarmente interessante quando l'applicazione deve gestire carichi variabili. In un ambiente cloud, ad esempio, il numero delle istanze può aumentare quando il traffico supera determinati valori e diminuire quando la domanda torna normale. Il load balancer diventa quindi il punto attraverso il quale le nuove istanze vengono integrate nell'architettura.

Per funzionare correttamente, questo modello richiede però un'applicazione progettata per operare in un ambiente distribuito. Se esistono dipendenze locali, sessioni memorizzate sul filesystem o configurazioni differenti tra i server, l'aggiunta automatica di nuovi nodi può generare problemi.

Monitoraggio e analisi delle prestazioni

Un sistema di load balancing deve essere monitorato in modo continuo perché rappresenta un componente critico dell'infrastruttura. Non è sufficiente verificare che il servizio sia raggiungibile. È necessario analizzare il numero di richieste al secondo, il numero di connessioni attive, la latenza, gli errori HTTP, i tempi di risposta dei backend e lo stato degli health check.

Questi dati permettono di capire dove si trova effettivamente il problema. Un aumento della latenza può dipendere dal load balancer, dalla rete, dal server applicativo oppure dal database. Un incremento degli errori HTTP 5xx può indicare invece un problema sul backend, mentre un aumento delle connessioni rifiutate può essere associato alla saturazione di una risorsa infrastrutturale.

La raccolta centralizzata dei log è particolarmente importante negli ambienti distribuiti. Registrando quale backend ha elaborato ogni richiesta è possibile correlare un errore con uno specifico nodo e individuare più rapidamente eventuali anomalie.

Load balancing e sicurezza

Il load balancer può svolgere anche un ruolo nella sicurezza dell'infrastruttura. Posizionato davanti ai server applicativi, può filtrare determinate richieste, applicare limiti al numero di connessioni o integrarsi con sistemi Web Application Firewall. In presenza di traffico anomalo, il rate limiting può contribuire a evitare che un numero eccessivo di richieste raggiunga direttamente l'applicazione.

Questo non significa che il load balancer possa sostituire la sicurezza applicativa. Ogni backend deve continuare a gestire correttamente autenticazione, autorizzazione, validazione degli input e protezione delle API. Il bilanciatore deve essere considerato come un ulteriore livello dell'architettura di sicurezza e non come l'unico meccanismo di protezione.

Progettare correttamente un'infrastruttura con load balancing

La progettazione di un sistema di load balancing deve partire dall'analisi del traffico e dell'applicazione. È necessario capire quante richieste devono essere gestite, quali sono i picchi di carico, quanto deve essere rapido il failover e quali componenti mantengono stato locale. Da queste informazioni è possibile stabilire se utilizzare Layer 4 o Layer 7, quale algoritmo di distribuzione adottare, come configurare gli health check e quale livello di persistenza delle sessioni sia necessario.

Devono essere analizzati anche i sistemi a valle del load balancer. Server applicativi, database, storage, firewall e rete devono essere dimensionati in modo coerente. Un load balancer molto potente collegato a backend insufficienti non migliora automaticamente le prestazioni dell'applicazione, così come più web server collegati a un database completamente saturo non eliminano il collo di bottiglia.

La progettazione deve inoltre prevedere procedure di monitoraggio, logging, backup della configurazione e test di failover. Una configurazione di alta disponibilità non dovrebbe essere considerata affidabile semplicemente perché è stata implementata: deve essere verificata attraverso test controllati che simulino la perdita di un nodo e misurino il comportamento dell'intero sistema.

Il load balancing come componente dell'infrastruttura moderna

Il load balancing rappresenta quindi molto più di un semplice sistema per dividere il traffico tra server. È un componente architetturale che permette di collegare scalabilità, disponibilità, sicurezza e gestione del traffico all'interno di un'unica infrastruttura. La distribuzione delle richieste tra più nodi permette di evitare la dipendenza da un singolo server e rende possibile aumentare progressivamente la capacità dell'ambiente attraverso la scalabilità orizzontale.

Per ottenere un risultato realmente efficace è però necessario progettare il sistema considerando anche sessioni, database, rete, TLS, health check, monitoraggio e ridondanza. Il load balancer deve essere inserito all'interno di un'architettura coerente, nella quale ogni componente critico sia analizzato rispetto alle proprie dipendenze e ai possibili punti di guasto.

In un'infrastruttura aziendale moderna, la corretta distribuzione del traffico permette quindi di gestire in modo più efficiente la crescita degli utenti e delle richieste, mantenendo sotto controllo le prestazioni e aumentando la resilienza dei servizi. La scelta della tecnologia di bilanciamento, dell'algoritmo di distribuzione e dell'architettura dei backend deve essere effettuata sulla base del comportamento reale dell'applicazione e dei requisiti di disponibilità, evitando configurazioni standard applicate senza una preventiva analisi tecnica.