2012-09-03 14 views
14

Conosci un modo efficiente per registrare l'utilizzo della memoria di un'applicazione django per richiesta?Come registrare l'utilizzo della memoria di un'applicazione Django per richiesta

Ho uno stack apache/mod_wsgi/django, che funziona normalmente bene, ma a volte un processo finisce per consumare molta memoria. I server finiscono per essere a corto di mem, scambiano molto e i servizi sono drasticamente rallentati.

Questa situazione è piuttosto difficile da risolvere perché non conosco quale richiesta debba essere incolpata per questo comportamento, non riesco a riprodurlo.

Mi piacerebbe avere qualcosa distribuito in produzione che registra l'utilizzo della memoria del processo prima e dopo ogni richiesta, con un sovraccarico minimo.


Prima di iniziare reinventare la ruota, fare la comunità dei miei compagni djangoists so Qualsiasi soluzione esistente per affrontare questo problema? Apprezzati, middleware, snippet o magari la configurazione del registro Apache apprezzata.

Quello che (credo) non ho bisogno è:

  • una serie di dev-stage strumenti di profilazione/debug, ho già delle conoscenze e io li userei se sapessi cosa al profilo/debug, sembra un po 'troppo per essere sempre monitorato i servizi in esecuzione in produzione. Oltre a ciò, ciò che viene solitamente visualizzato da quei tol è un rapporto sull'uso del codice del frammento del codice in pezzi, sarebbe davvero utile solo individuare la richiesta difettosa.
  • consigli generici su come ottimizzare l'utilizzo di mem di un'applicazione django, beh è sempre una buona lettura, ma l'idea qui è piuttosto «come rintracciare in modo efficiente le richieste che devono essere ottimizzate».

I miei risultati di ricerca più vicini:

+0

Forse questa opzione modwsgi 'maximum-requests = nnn' aiuterà. "Definisce un limite al numero di richieste che un processo daemon deve elaborare prima di essere arrestato e riavviato." – freestyler

+0

@freestyler: sì, lo uso già, ma manca il punto. L'idea è di mettere in luce richieste difettose per correggerle effettivamente, non per disinfettare periodicamente il sistema (che potrebbe essere anche utile). Inoltre, una richiesta che consuma memoria potrebbe apparire presto dopo un riavvio, nessuna correlazione qui. – ddelemeny

risposta

14

Un middleware Django per il monitoraggio dell'utilizzo della memoria e la generazione immediata di un risultato utilizzabile, deve agganciare sia la richiesta di processo che la risposta di processo. In altre parole, guarda la differenza tra inizio e fine della richiesta e registra un avviso se supera una soglia.

Un esempio completo middleware è:

import os 
import psutil 
import sys 

THRESHOLD = 2*1024*1024 

class MemoryUsageMiddleware(object): 

    def process_request(self, request): 
     request._mem = psutil.Process(os.getpid()).get_memory_info() 

    def process_response(self, request, response): 
     mem = psutil.Process(os.getpid()).get_memory_info() 
     diff = mem.rss - request._mem.rss 
     if diff > THRESHOLD: 
      print >> sys.stderr, 'MEMORY USAGE %r' % ((diff, request.path),) 
     return response 

Questo richiede il modulo 'psutil' per essere installato per fare il calcolo di memoria.

È forza bruta e può portare a falsi positivi in ​​un sistema multithread. A causa del caricamento lento, si vedrà anche il trigger sulle prime poche richieste contro il nuovo processo man mano che la roba viene caricata.

+0

È pulito, grazie per la risposta! I falsi positivi non sono realmente un problema in quanto lo scopo è solo quello di innescare e focalizzare ulteriori indagini, accoppiando queste informazioni con PID e data/ora può aiutare a capire ed eliminare rapidamente questi casi. Come nota a margine, potrebbe valere la pena di inserirlo in un middleware WSGI, in modo che non sia legato alla macchina del django. – ddelemeny

+0

Per farlo correttamente come un middleware WSGI diventa orribilmente più complicato. Quando l'ho fatto è stato per un utente Django, quindi è più facile farlo come un middleware Django. :-) –

+0

Oh, sì, certo! Era solo uno spunto di riflessione, non mi aspettavo che tu tirassi fuori un middleware WSGI. In effetti, non mi aspettavo che qualcuno creasse un middleware django dal nulla per rispondere alla mia domanda, grazie per quello! SO community sembra abbastanza impressionante ;-) – ddelemeny

1

Questo non può coprire completamente la tua domanda, ma vi consiglio di provare nginx + uwsgi invece di apache2 + mod_wsgi. Nei miei test si è rivelato molto più stabile (il mod_wsgi è stato bloccato a un certo punto completamente), molto più veloce e utilizza molta meno memoria (potrebbe semplicemente risolvere tutti i problemi del tutto).

A proposito di monitoraggio l'utilizzo della memoria, è possibile creare un semplice middleware:

class SaveMemoryUsageMiddleware(object): 
    def process_response(self, request, response): 
     # track memory usage here and append to file or db 
     return response 

e aggiungerlo ai tuoi middleware.

Per codice di monitoraggio di memoria mi consiglia di controllare: Total memory used by Python process?

Tuttavia, sarebbe probabilmente meglio se si potesse evitare di fare questo sulla produzione. Solo per sviluppatori e test per rintracciare il vero problema.

+0

Grazie per la risposta, la sostituzione di apache è in qualche modo pianificata, ma a bassa priorità. Nginx è già in cima al mio stack. Il modo middleware è il tipo di cosa che stavo progettando di fare se nessuno fosse riuscito a trovare una soluzione esistente. Grazie per i suggerimenti sul monitoraggio del consumo di memoria all'interno di python, è probabile che sia di aiuto. – ddelemeny

+1

Se Apache ha usato molta più memoria, allora si imposta Apache su sbagliato, semplice. Guarda la mia discussione su PyCon in quanto copre l'errore comune che le persone fanno di usare le impostazioni predefinite di Apache. http://lanyrd.com/2012/pycon/spcdg/ –

+0

C'è una grande differenza su come nginx e apache2 funzionano internamente. Non ci si può aspettare che il pool basato su processo/thread (apache) utilizzi per caso una quantità di memoria simile a quella del pool basato su eventi (nginx). Semplice come quella. – arkens

Problemi correlati