Tengo un script de Python ejecutando Django para la base de datos y Memcache, pero está ejecutando notablemente como daemon independiente (es decir, no responde a las solicitudes del servidor web). El daemon comprueba una solicitud de modelo Django para objetos con un status=STATUS_NEW
, luego los marca STATUS_WORKING y los coloca en una cola.Python/Django sondeo de base de datos tiene pérdida de memoria
Varios procesos (creados con el paquete de multiprocesos) sacarán cosas de la cola y trabajarán en la solicitud con el pr.id
que se pasó a la cola. Creo que la pérdida de memoria es, probablemente, en el siguiente código (pero podría ser en el código 'trabajador' en el otro lado de la cola, aunque esto es poco probable, porque debido a que el tamaño de la memoria está creciendo incluso cuando no hay Solicitudes están subiendo - es decir, cuando todos los trabajadores están bloqueando en Queue.get()).
from requisitions.models import Requisition # our Django model
from multiprocessing import Queue
while True:
# Wait for "N"ew requisitions, then pop them into the queue.
for pr in Requisition.objects.all().filter(status=Requisition.STATUS_NEW):
pr.set_status(pr.STATUS_WORKING)
pr.save()
queue.put(pr.id)
time.sleep(settings.DAEMON_POLL_WAIT)
Donde settings.DAEMON_POLL_WAIT=0.01
.
Parece que si salgo de esta corriente por un período de tiempo (es decir, un par de días) el proceso de Python crecerá a tamaño infinito y, finalmente, el sistema se quede sin memoria.
lo que está pasando aquí (o cómo puedo averiguar), y lo más importante - ¿cómo se puede ejecutar un demonio que hace esto?
Mi primer pensamiento es para cambiar la dinámica de la función, en particular, poniendo el cheque de nueva Solicitud objetos en un django.core.cache cache
, es decir
from django.core.cache import cache
while True:
time.sleep(settings.DAEMON_POLL_WAIT)
if cache.get('new_requisitions'):
# Possible race condition
cache.clear()
process_new_requisitions(queue)
def process_new_requisitions(queue):
for pr in Requisition.objects.all().filter(status=Requisition.STATUS_NEW):
pr.set_status(pr.STATUS_WORKING)
pr.save()
queue.put(pr.id)
El proceso que está creando Solicitudes con status=STATUS_NEW
puede hacer un cache.set('new_requisitions', 1)
(o como alternativa, podríamos capturar una señal o evento Requisition.save() donde se está creando una nueva solicitud y luego establecer la bandera en la memoria caché desde allí).
Sin embargo, no estoy seguro de que la solución que he propuesto aborde los problemas de memoria (que probablemente estén relacionados con la recolección de basura, por lo que el alcance por medio del process_new_requisitions
puede resolver el problema).
estoy agradecido por cualquier pensamientos y comentarios.
Es sólo una idea ... ¿Usted está funcionando con debug = true en settings.py? El modo de depuración guarda todas las consultas, lo que sin duda puede parecer una pérdida de memoria :) –
Heh heh. ¡Lo fui, de hecho! Me olvide de eso. Lo he apagado (y me he movido a la solución de caché) y la pérdida de memoria parece haber disminuido. –