Siti web che mettono alla prova

27 settembre 2017

Se gestisci un sito che riporta puntualmente, ogni domenica, i risultati in tempo reale di tutti i tornei di calcio della regione, dilettantistici e non, ecco che la domenica pomeriggio, verso le 16:30, di solito hai un problema importante.

Nell'epoca dell'informazione tutta e subito, chi può ancora immaginare di attendere le espertissime voci del bar per avere gli aggiornamenti dai vari campi del territorio?

Fornire però le classifiche a migliaia di persone che di fatto bussano contemporaneamente alla porta del tuo sito per avere i dati aggiornati dell'ultimo minuto, genera una sfida importante.

 
Picco di traffico nel pomeriggio della domenica: +600% rispetto al traffico "standard"
(si tratta di oltre il doppio degli accessi di un e-commerce da 1000 ordini al giorno!)

 










Per evitare i costi di un server con tutta la memoria e la potenza di calcolo sufficiente a fare fronte alle richieste, c'è una soluzione che non è certo nuova, ma il corretto fine tuning richiede un po' di attenzione. La risposta si chiama reverse proxying, nel nostro caso egregiamente implementata da nginx.

 

I punti chiave sono sostanzialmente tre:

Proxy Cache

Quando una persona richiede la pagina delle classifiche di un determinato girone, questa, una volta elaborata, viene mantenuta per circa 60 sec. in una apposita cache in modo da poter rispondere rapidamente ad altre richieste analoghe senza impegnare nuove risorse da parte dell'applicazione. Dopodiché, una volta scaduto il tempo impostato, a fronte di una nuova richiesta, avverrà una nuova rielaborazione della pagina per fornire una versione aggiornata della classifica. (il tempo di validità della cache è breve perché stiamo parlando di dati molto dinamici, però per il server che deve ricalcolare le pagine non più di una volta al minuto, invece che continuamente, fa una differenza enorme).

Proxy Cache Lock

Se al server nginx arriva la richiesta di una pagina non presente in cache, oppure presente ma con una copia scaduta, la richiesta viene di norma passata all'applicazione per un ricalcolo. Ma non è infrequente nei periodi di picco che durante la fase di elaborazione della pagina arrivino molte altre decine di richieste che non trovando una versione in cache pronta che verrebbero normalmente passate all'applicazione per una nuova elaborazione (inutile e costosa, dato che il server sta già preparando la pagina richiesta). Nel nostro caso queste nuove richieste vengono riconosciute e messe in attesa, in modo che, all'arrivo della risposta per il primo degli utenti, questa venga inviata contemporaneamente a tutti quelli che nel frattempo hanno effettuato una richiesta analoga.

Buffering

Quest'ultima ottimizzazione invece è particolarmente tricky e non sempre ovvia anche agli addetti ai lavori.

Quando una richiesta non presente in cache viene passata all'applicazione, di solito è quest'ultima che si occupa di inviare, direttamente al client che l'ha richiesta, la risposta appena elaborata dinamicamente. Ma se il client è in una situazione particolarmente sfavorevole dal punto di vista della connettività (caso non poi così raro), anche solo tramettere poche decine di Kb può richiedere molte decine di secondi. In tutto questo tempo il processo è sostanzialmente bloccato e non può servire nuove richieste.

Basta un ridotto numero di utenti in queste condizioni che facilmente anche un server dotato di molte risorse può essere messo facilmente in ginocchio.

Nel nostro caso questo problema è stato scongiurato in quanto la pagina prodotta dall'applicativo dinamicamente passa sempre da un apposito buffer lasciando immediatamente libero il processo applicativo di gestire altre richieste.

Attenzione: non esistono soluzioni preconfezionate che valgano per tutti, analizzare ogni situazione, capirla e sfruttarne le caratteristiche proprie è la strada maestra per arrivare.

 

Ing. Danilo Stefani 

 

Nota: il sito citato è www.romagnasport.com

Condividi l'articolo!