【发布时间】:2010-02-25 22:08:13
【问题描述】:
我有一个 Python 脚本运行 Django 用于数据库和内存缓存,但它特别是作为一个独立的守护进程运行(即不响应网络服务器请求)。守护程序检查 Django 模型申请中带有 status=STATUS_NEW 的对象,然后将它们标记为 STATUS_WORKING 并将它们放入队列中。
许多进程(使用多进程包创建)将从队列中拉出事物并使用传递给队列的pr.id 处理申请。我相信内存泄漏可能在以下代码中(但它可能在队列另一侧的“工人”代码中,尽管这不太可能,因为即使没有申请出现,内存大小也在增长 - 即当工作人员都在 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)
settings.DAEMON_POLL_WAIT=0.01.
如果我让它运行一段时间(即几天),Python 进程将增长到无限大小,最终系统将耗尽内存。
这里发生了什么(或者我怎样才能知道),更重要的是 - 你如何运行一个守护进程来做到这一点?
我的第一个想法是改变函数的动态,特别是将新申请对象的检查放入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)
使用status=STATUS_NEW 创建申请的进程可以执行cache.set('new_requisitions', 1)(或者我们可以捕获正在创建新申请的信号或 Requisition.save() 事件,然后从那里设置缓存中的标志)。
但是我不确定我在这里提出的解决方案是否解决了内存问题(这可能与垃圾收集有关 - 因此通过process_new_requisitions 进行范围界定可能会解决问题)。
感谢您的任何想法和反馈。
【问题讨论】:
-
只是一个想法...您是否在 settings.py 中使用 DEBUG=True 运行?调试模式保存所有查询,这肯定看起来像内存泄漏:)
-
嘿嘿。我是,确实!我忘记了。我已将其关闭(并移至缓存解决方案),内存泄漏似乎已减少。
标签: python django memory-leaks daemon