2012-09-03 10 views
14

Kennen Sie eine effiziente Möglichkeit, die Speichernutzung einer Django-App pro Anfrage zu protokollieren?So protokollieren Sie die Speicherauslastung einer Django-App pro Anfrage

Ich habe einen Apache/Mod_wsgi/Django-Stack, der normalerweise gut läuft, aber manchmal endet ein Prozess eine riesige Menge an Speicher. Die Server haben wenig Speicher, sie tauschen viel aus und die Dienste werden drastisch verlangsamt.

Diese Situation ist ziemlich schwer zu beheben, weil ich nicht weiß, welche Anfrage für dieses Verhalten verantwortlich gemacht werden soll, ich kann es nicht reproduzieren.

Ich möchte etwas in der Produktion bereitgestellt haben, die die Speicherauslastung des Prozesses vor und nach jeder Anfrage mit minimalem Overhead protokolliert.


Bevor ich das Rad neu zu erfinden starten, tun die Gemeinde meiner Kollegen djangoists kennt jede bestehende Lösung dieses Problem zu lösen? Hinweise, Middleware, Snippet oder vielleicht Apache Log-Konfiguration geschätzt.

Was (glaube ich) Ich brauche nicht ist:

  • eine Reihe von Entwickler-Stufe Profilierung/Debugging-Tool, ich weiß, einige von ihnen bereits und ich würde sie benutzen, wenn ich weiß, was zum Profil/debuggen, es sieht ein bisschen zu viel aus, um für immer in der Produktion laufende Dienste zu überwachen. Obendrein wird normalerweise ein Mem-Verwendungs-Bericht des Code-Shred in Stücke angezeigt. Es wäre wirklich hilfreich, die fehlerhafte Anfrage genau zu lokalisieren.
  • generische Ratschläge zur Optimierung der Speicherbelegung einer Django App, gut, es ist immer gut zu lesen, aber die Idee hier ist eher «wie Anfragen effizient zu verfolgen, die optimiert werden müssen».

Meine engsten Suchergebnisse:

+0

Vielleicht hilft diese modwsgi Option 'Maximum-Anfragen = nnn'. "Definiert ein Limit für die Anzahl der Anforderungen, die ein Daemon-Prozess verarbeiten soll, bevor er heruntergefahren und neu gestartet wird." – freestyler

+0

@freestyler: yep, ich benutze das schon, aber es vermisst den Punkt irgendwie. Die Idee besteht darin, fehlerhafte Anfragen zu beleuchten, um sie tatsächlich zu reparieren, um das System nicht periodisch zu bereinigen (was auch nützlich sein könnte). Außerdem könnte eine speicherverbrauchende Anfrage früh nach einem Neustart erscheinen, hier keine Korrelation. – ddelemeny

Antwort

14

Eine Django-Middleware zum Verfolgen der Speichernutzung und zum sofortigen Erzeugen eines verwendbaren Ergebnisses muss sowohl die Prozessanforderung als auch die Prozessantwort haken. Mit anderen Worten: Sehen Sie sich den Unterschied zwischen dem Start und dem Ende der Anfrage an und protokollieren Sie eine Warnung, wenn ein bestimmter Schwellenwert überschritten wird.

Eine komplette Middleware Beispiel ist:

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 

Dies erfordert die ‚psutil‘ Modul dafür Speicher Berechnung installiert werden.

Brute Force und kann zu Fehlalarmen in einem Multithread-System führen. Aufgrund von Lazy Loading werden Sie auch sehen, dass es bei ersten Anfragen gegen einen neuen Prozess ausgelöst wird, wenn der Inhalt geladen wird.

+0

Das ist nett, danke für die Antwort! Falsche Positives sind nicht wirklich ein Problem, da der Zweck nur darin besteht, weitere Untersuchungen auszulösen und zu fokussieren. Das Koppeln dieser Informationen mit PID und Datum/Zeit kann helfen, diese Fälle schnell zu verstehen und zu eliminieren. Als Nebenbemerkung könnte es sich lohnen, dies in eine WSGI-Middleware zu stellen, so dass es nicht an die Django-Maschinerie gebunden ist. – ddelemeny

+0

Um es richtig als WSGI-Middleware zu tun, wird fürchterlich komplizierter. Als ich das gemacht habe, war es für Django-Benutzer, also einfacher, es als Django-Middleware zu machen. :-) –

+0

Oh, ja, sicher! Es war nur Essen für Gedanken, ich habe nicht erwartet, dass Sie eine WSGI-Middleware herauspeitschen. Tatsächlich habe ich nicht erwartet, dass irgendjemand aus heiterem Himmel eine Django-Middleware erstellt, um meine Frage überhaupt zu beantworten, danke dafür! SO Community sieht ziemlich genial aus ;-) – ddelemeny

1

Dies kann vollständig Ihre Frage nicht abdecken, aber ich empfehlen daher, nginx + uwsgi statt apache2 + mod_wsgi. In meinen Tests stellte es sich als viel stabiler heraus (mod_wsgi erstickte irgendwann vollständig), viel schneller und benötigt viel weniger Speicher (es kann nur alle deine Probleme beheben).

Über Speichernutzung Tracking, können Sie eine einfache Middleware erstellen:

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

und fügen Sie sie der Middle.

Für Tracking-Code-Speicher Ich empfehle, Check-out: Total memory used by Python process?

Es ist jedoch wahrscheinlich besser wäre, wenn Sie tun dies auf Produktion vermeiden können. Nur für Dev und Tests, um echtes Problem aufzuspüren.

+0

Danke für die Antwort, Apache zu ersetzen ist irgendwie geplant, aber niedrige Priorität. Nginx ist bereits ganz oben auf meinem Stack. Der Middleware-Weg ist die Art von Sache, die ich vorhatte, wenn niemand eine existierende Lösung hätte. Danke für die Hinweise zur Speicherverbrauchsüberwachung in Python, die wahrscheinlich helfen werden. – ddelemeny

+1

Wenn Ihr Apache viel mehr Speicher verwendet hat, dann haben Sie Apache falsch eingerichtet, einfach so. Beobachten Sie mein PyCon-Gespräch, da es den üblichen Fehler der Apache-Standardeinstellungen behandelt. http://lanyrd.com/2012/pycon/spcdg/ –

+0

Es gibt einen großen Unterschied, wie nginx und apache2 intern funktioniert. Sie können nicht erwarten, dass Prozess/thread-basierter Pool (Apache) mit Sicherheit ähnliche Speichermengen verwendet wie der ereignisbasierte Pool (nginx). So einfach ist das. – arkens

Verwandte Themen