2012-09-03 11 views
14

¿Conoces una forma eficiente de registrar el uso de la memoria de una aplicación django por solicitud?Cómo registrar el uso de la memoria de una aplicación Django por solicitud

Tengo una pila apache/mod_wsgi/django, que normalmente funciona bien, pero a veces un proceso termina consumiendo una gran cantidad de memoria. Los servidores terminan siendo cortos en mem, intercambiando mucho, y los servicios se reducen drásticamente.

Esta situación es bastante difícil de solucionar porque no sé qué pedido se debe a este comportamiento, no puedo reproducirlo.

Me gustaría tener algo implementado en producción que registre el uso de la memoria del proceso antes y después de cada solicitud, con una sobrecarga mínima.


Antes de empezar a reinventar la rueda, hacer la comunidad de mis compañeros djangoists conozco a ninguna solución existente para hacer frente a este problema? Apreciación de los advices, middleware, snippet o tal vez configuración de registro de Apache.

Lo que (creo) que no necesito es:

  • un conjunto de herramientas de perfilado/dev depuración etapa, que ya saben algunos y que haría uso de ellos si yo sabía qué perfil/depurar, parece un poco demasiado para supervisar para siempre los servicios que se ejecutan en producción. Además de eso, lo que usualmente muestran esos usuarios es un informe de uso de memoria del código fragmentado en pedazos. Sería realmente útil simplemente identificar la solicitud defectuosa.
  • consejos genéricos sobre cómo optimizar el uso de mem de una aplicación django, bueno, siempre es bueno leer, pero la idea aquí es más bien "cómo rastrear eficientemente las solicitudes que deben optimizarse".

Mis más próximos resultados de la búsqueda:

+0

Tal vez esta opción de modmsgi 'maximum-requests = nnn' ayude. "Define un límite en el número de solicitudes que un proceso daemon debe procesar antes de que se cierre y se reinicie." – freestyler

+0

@freestyler: sí, ya lo uso, pero pasa algo por alto. La idea es aclarar las solicitudes defectuosas para realmente arreglarlas, no para desinfectar el sistema periódicamente (lo que también podría ser útil). Además, una solicitud de consumo de memoria podría aparecer temprano después de un reinicio, sin correlación aquí. – ddelemeny

Respuesta

14

Un middleware Django para rastrear el uso de la memoria y generar un resultado utilizable de inmediato, necesita enganchar tanto la solicitud de proceso como la respuesta del proceso. En otras palabras, observe la diferencia entre el inicio y el final de la solicitud y registre una advertencia si supera algún umbral.

Un ejemplo completo de middleware es:

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 

Esto requiere el módulo 'psutil' para ser instalado para hacer cálculo de memoria.

Es la fuerza bruta y puede dar lugar a falsos positivos en un sistema de múltiples hilos. Debido a la carga diferida, también se activará en las primeras solicitudes contra un nuevo proceso, ya que las cosas se cargan.

+0

¡Eso está bien, gracias por la respuesta! Los falsos positivos no son realmente un problema, ya que el propósito es solo activar y enfocar una investigación más profunda, el acoplamiento de esta información con el PID y la fecha/hora pueden ayudar a comprender y eliminar esos casos rápidamente. Como nota al margen, puede valer la pena colocar esto en un middleware WSGI, para que no esté vinculado a la maquinaria django. – ddelemeny

+0

Para hacerlo correctamente como un middleware WSGI se vuelve terriblemente más complicado. Cuando lo hice, fue para usuarios de Django, así que es más fácil hacerlo como middleware de Django. :-) –

+0

¡Oh, sí, claro! Era solo alimento para pensamientos, no esperaba que sacara un middleware de WSGI. De hecho, no esperaba que alguien creara un middleware django de la nada para responder mi pregunta, ¡gracias por eso! La comunidad SO se ve bastante impresionante ;-) – ddelemeny

1

Esto no puede cubrir totalmente su pregunta, pero yo recomendaría probar nginx + uwsgi en lugar de apache2 + mod_wsgi. En mis pruebas, resultó ser mucho más estable (mod_wsgi ahogado en algún momento por completo), mucho más rápido y usa mucha menos memoria (puede solucionar todos sus problemas por completo).

Sobre el seguimiento de uso de la memoria, puede crear un middleware simple:

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

y añadirlo a sus middleware.

Para código de seguimiento de memoria recomiendo echar un vistazo a: Total memory used by Python process?

Sin embargo, probablemente sería mejor si se pudiera evitar hacer esto en la producción. Solo para desarrolladores y pruebas para localizar un problema real.

+0

Gracias por la respuesta, reemplazar apache de alguna manera está planeado, pero de baja prioridad. Nginx ya está en la cima de mi stack. El middleware es el tipo de cosas que planeaba hacer si nadie pudiera encontrar una solución. Gracias por los consejos sobre el control del consumo de memoria dentro de python, es probable que eso ayude. – ddelemeny

+1

Si su Apache usó mucha más memoria, entonces configura Apache incorrecto, así de simple. Mire mi charla PyCon ya que cubre el error común que las personas cometen al usar los valores predeterminados de Apache. http://lanyrd.com/2012/pycon/spcdg/ –

+0

Hay una gran diferencia en cómo nginx y apache2 funcionan internamente. No puede esperar que el grupo basado en procesos/subprocesos (apache) use por casualidad cantidades similares de memoria como grupo basado en eventos (nginx). Simple como eso. – arkens

Cuestiones relacionadas