Python/Django数据库轮询有内存泄漏

Bri*_*unt 15 python django memory-leaks daemon

我有一个运行Django的Python脚本用于数据库和内存缓存,但它特别是作为一个独立的守护进程运行(即不响应webserver请求).守护进程检查带有a的对象的Django模型申请单status=STATUS_NEW,然后将它们标记为STATUS_WORKING并将它们放入队列中.

许多进程(使用多进程包创建)将从队列中提取出来并使用pr.id传递给队列的Requisition进行处理.我相信内存泄漏可能在下面的代码中(但它可能在Queue另一端的'Worker'代码中虽然这不太可能,因为即使没有请购单即将出现,内存大小也在增长 - 即当工作者都在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)
Run Code Online (Sandbox Code Playgroud)

哪里settings.DAEMON_POLL_WAIT=0.01.

看来,如果我让它运行一段时间(即几天),Python进程将增长到无限大,最终系统将耗尽内存.

这里发生了什么(或者我怎么能找到),更重要的是 - 你怎么能运行这样做的守护进程?

我的第一个想法是改变函数的动态,特别是通过检查新的Requisition对象django.core.cache cache,即

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)
Run Code Online (Sandbox Code Playgroud)

创建申请单的过程status=STATUS_NEW可以执行cache.set('new_requisitions', 1)(或者我们可以捕获正在创建新申请单的信号或Requisition.save()事件,然后从那里设置缓存中的标记).

但是我不确定我在这里提出的解决方案是否解决了内存问题(可能与垃圾收集有关 - 因此通过方式确定process_new_requisitions可以解决问题).

我很感激任何想法和反馈.

Lud*_*mer 38

您需要定期重置Django为调试目的而保留的查询列表.通常它会在每次请求后清除,但由于您的应用程序不是基于请求的,因此您需要手动执行此操作:

from django import db

db.reset_queries()
Run Code Online (Sandbox Code Playgroud)

也可以看看:


Dan*_*man 5

守护进程的settings.py文件是否有DEBUG = True?如果是这样,Django会在内存中记录到目前为止运行的所有SQL,这可能会导致内存泄漏.