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)
也可以看看:
Mikko Ohtamaa 用"TrackRefs和Guppy调试Django内存泄漏":
Django会跟踪所有查询以进行调试(connection.queries).此列表在HTTP请求结束时重置.但在独立模式下,没有请求.因此,您需要在每个工作周期后手动重置为查询列表
"为什么Django会泄露记忆?" 在Django常见问题 -它谈到双方有关设置DEBUG
到False
,这始终是重要的,有关清除使用的查询列表db.reset_queries()
中,像你这样的应用很重要.
归档时间: |
|
查看次数: |
7875 次 |
最近记录: |