2013-03-05 9 views
9

Sto cercando di capire perché il mio sito django (gunicorn 4 operai) è lento sotto carico, ho fatto qualche profilazione http://djangosnippets.org/snippets/186/ senza alcuna risposta chiara quindi ho iniziato alcuni test di carico da zero utilizzando ab -n 1000 -c 100 http://localhost:8888/Django, richieste basse al secondo con gunicorn 4 lavoratori

Un semplice Httpreponse ("ciao mondo") senza middleware ==> 3600req/s

Un semplice Httpreponse ("ciao mondo"), con middleware (sessione memorizzata nella cache, l'autenticazione cache) ==> 2300req/s

Un semplice render_to_response che stampa solo un modulo (modello memorizzato nella cache) ==> 12 00req/s (tempo di risposta è stato diviso per due)

Un semplice render_to_response con 50 interrogazioni al database memcache ==> 157req/s

query Memcache dovrebbe essere molto più veloce di quello (sto usando PyLibMCCache)? Il rendering del modello è lento come questo?

Ho provato diverse tecniche di profiling senza alcun successo.

$ ulimit -a 
core file size   (blocks, -c) 0 
data seg size   (kbytes, -d) unlimited 
scheduling priority    (-e) 0 
file size    (blocks, -f) unlimited 
pending signals     (-i) 46936 
max locked memory  (kbytes, -l) 64 
max memory size   (kbytes, -m) unlimited 
open files      (-n) 400000 
pipe size   (512 bytes, -p) 8 
POSIX message queues  (bytes, -q) 819200 
real-time priority    (-r) 0 
stack size    (kbytes, -s) 8192 
cpu time    (seconds, -t) unlimited 
max user processes    (-u) 46936 
virtual memory   (kbytes, -v) unlimited 
file locks      (-x) unlimited 

$ sysctl -p 

fs.file-max = 700000 
net.core.somaxconn = 5000 
net.ipv4.tcp_keepalive_intvl = 30 

sto usando Ubuntu 12.04 (6Go di ram, Core i5)

Qualsiasi aiuto per favore?

+1

+1 per la ricerca che hai effettuato – Private

+0

Dipende ... che cosa fai nelle viste? quali domande esegui? su cosa li gestisci? – ionelmc

+0

è il tuo server memcached sullo stesso computer o su uno esterno? –

risposta

1

Dipende molto da quanto tempo ci vuole per fare una richiesta memcached e per aprire una nuova connessione (django chiude la connessione al termine della richiesta), sia il tuo worker che memcached sono in grado di gestire molto più stress ma, naturalmente, se ci vogliono 5/10ms per fare una chiamata memcached e 50 di questi saranno il collo di bottiglia dato che la latenza della rete è moltiplicata per il conteggio delle chiamate.

In questo momento si sta solo analizzando il django, la gunicorn, la macchina e la rete.

A meno che tu non abbia qualcosa di estremamente sbagliato a questo livello, questi test non ti porteranno a scoperte molto interessanti.

Ciò che rallenta la tua app è molto probabilmente correlato al modo in cui usi il tuo db e memcached (e forse al rendering del template).

Per questo motivo ti suggerisco di utilizzare la barra degli strumenti di debug di django e vedere che cosa sta succedendo nelle tue pagine reali.

Se risulta che aprire una connessione a memcached è il collo di bottiglia, è possibile provare a utilizzare un pool di connessioni e mantenere la connessione aperta.

+0

Ho fatto tutto questo (memcache-debug-panel, profiling ...), fondamentalmente ho risolto il mio problema riducendo al minimo le query memcache e memorizzando il codice html direttamente su memcache (perché alcuni tag del template django sono molto lenti anche). facendo ciò ho moltiplicato il rapporto di rotazione/s * 100 – surfeurX

0

È possibile esaminare le prestazioni memcached.

$ python manage.py shell 
>>> from django.core.cache import cache 
>>> cache.set("unique_key_name_12345", "some value with a size representative of the real world memcached usage", timeout=3600) 
>>> from datetime import datetime 
>>> def how_long(n): 
     start = datetime.utcnow() 
     for _ in xrange(n): 
      cache.get("unique_key_name_12345") 
     return (datetime.utcnow() - start).total_seconds() 

Con questo tipo di test di andata e ritorno che sto vedendo che 1 lookup memcached vorranno circa 0,2 ms sul mio server.

Il problema con django.core.cache e pylibmc è che le funzioni stanno bloccando. Potenzialmente potresti ottenere 50 volte quel numero nel round trip per la richiesta HTTP. 50 volte 0,2 ms è già 10 ms.

Se si raggiungono 1200 req/s su 4 lavoratori senza memcached, il tempo medio di andata e ritorno HTTP era 1/(1200/4) = 3,33 ms. Aggiungi 10 ms a quello e diventa 13,33 ms. Il throughput con 4 worker scenderebbe a 300 req/s (che capita di essere nel ballpark del tuo numero 157).

Problemi correlati