On Fri, 2 Dec 2011 15:36:50 +0100, Alessandro Dentella wrote:

un cliente mi ha chiesto di aiutare a capire come rendere più veloce una
applicazione web che raccoglie dati da molti utenti differenti in
contemporanea (qualche centinaio) e si ingolfa in particolari momenti
del mese di maggior accesso.

Attualmente usano Tornado [1], un incrocio fra un server web ed un piccolo
framework (che tramite un decoratore permette di rendere una funzione
asincrona).

Non ho alcuna esperienza di Tornado, qualche esperienza con twisted e
qualche dubbio sul fatto che quel particolare problema abbia grandi vantaggi dall'approccio asincrono. L'applicazione lato client usa intensamente ajax e molte chiamate al server che fanno pochi conti ed una manciata di select
semplici o di piccole join. La macchina ha 4 processori e 4 GB di RAM
(principalmente libera). Ogni chiamata dallo stesso client cambia dati nella sessione che devono quindi essere sincronizzati fra una chiamata e l'altra.

Mi pare di capire che non tutte le applicazioni beneficiano del fatto di
funzionare in modalità asincrona: qui non esiste tempo di attesa
significativo di dati dalla rete e pare poco (forse migliorabile in ogni caso) dal database. Avete qualche suggerimento? Qualche opinione (o link
utile) sulla opportunità di usare un server così rispetto ad una
configurazione classica apache + mod_wsgi? Chiaramente l'obiettivo è di distribuire il carico di lavoro su tutti i processori e successivamente su
più macchine.

Io ho risolto da poco un problema del genere su un server che non ce la faceva più a scalare.

Prima nota che, sync con multithread, o async con green thread, più di una cpu non riesci a usarla bene in Python. Con i green thread la usi meglio che con i thread se il problema è I/O bound, ma resti sempre in un processo singolo.

Io ho messo 4 server in ascolto su 4 porte diverse: il primo sulla standard https 443 e altre 8444, 8445, 8446 (la bella copia sarebbe avere 4 sub-domain, ma per ora abbiamo solo un certificato ssh).

Quando un utente si connette, viene rediretto ad un certo nodo (id utente % n. nodi, per esempio). Da lì in poi tutti i link del programma sono relativi, per cui una volta che è andato sul server https://host:8445, ci resta. Il suo nodo di appartenenza è anche memorizzato al momento del login nella sua sessione del server: ad ogni richiesta viene controllato che sia sul server giusto e, se non lo è, gli viene servito un redirect per mandarcelo.

Questa soluzione consente di usare tutte le cpu sulla macchina nella maniera migliore possibile: con diversi processi. Perché funzioni si assume che gli utenti non si scambino dati tra loro se non attraverso il database. Invece poiché un utente resta sempre sullo stesso server, i suoi dati di sessione sono sempre disponibili. Per scalare di più possiamo aggiungere nuovi processi (la nostra macchina ha 16 cpu) o anche aggiungere nuove macchine.

Abbiamo messo in piedi il tutto in brevissimo tempo, senza modificare l'architettura di un applicativo che è un mammuth e nel quale ogni utente ha uno stato complicatissimo. È una soluzione completamente priva di magie (tipo sperare che la parola magica async risolva tutti i problemi...)

--
Daniele Varrazzo - Develer S.r.l.
http://www.develer.com
_______________________________________________
Python mailing list
Python@lists.python.it
http://lists.python.it/mailman/listinfo/python

Reply via email to