【问题标题】:Why Python does not release memory (under mod_wsgi + Django)为什么 Python 不释放内存(在 mod_wsgi + Django 下)
【发布时间】:2013-10-31 07:24:50
【问题描述】:

我有Apache + mod_wsgi + Django 应用程序。 mod_wsgi 以守护程序模式运行。

我有一个视图,它从数据库中获取重要的查询集,并通过计算查询集的结果另外分配数组,然后返回这个数组。我没有使用线程本地存储、全局变量或类似的东西。

问题是我的应用消耗内存相对于我为 mod_wsgi 设置的线程数

我做了一个小实验,通过在 mod_wsgi 中设置不同数量的线程,然后通过 curl 检查 wsgi 进程可以内存爬升多远来访问我的视图。

是这样的:

1 个线程 - 256Mb 2 个线程 - 400Mb 3 个线程 - 535Mb 4 线程 - 650Mb

所以每个线程在最高内存使用量上增加了大约 120-140Mb。

我似乎永远不会释放为第一个请求分配的初始内存。在单线程场景中,当第二个请求(对同一视图)到达时,它会被重用。这样我就可以离开了。

但是当我使用多个线程时,当请求由以前从未运行过此请求的线程处理时,该线程会在本地某处“保存”另外 140mb。

  • 如何解决这个问题?
  • 可能 Django 在 TSL 中保存了一些数据。如果那是 这种情况下,我该如何禁用它?
  • 或者,作为一种解决方法,是 可以将请求执行绑定到mod_wsgi中的某个线程吗?

谢谢。

PS。 DEBUGsettings.py 中设置为 False

【问题讨论】:

  • 您是否 a) 仅在数据集到达时创建数组,b) 在完成后将其删除,以便垃圾收集器可以访问它?
  • a) - 是的; b) - 我没有明确地删除它。我将其转换为 JSON 并返回 JSON 字符串。
  • 不删除它还在使用中!
  • 这不是真的。只要事物没有以某种方式显式缓存,它们就应该能够在使用它们的最后一个作用域退出时立即清理。唯一可能不是这种情况的情况是数据在对象之间创建了引用计数循环,在这种情况下,需要等待垃圾收集器启动并尽可能打破循环。
  • OP 没有明确说明的是在多线程情况下,请求是序列化的还是同时运行的。如果序列化,由于它管理线程的方式,最多 mod_wsgi 守护程序模式应该只激活两个线程而不是四个。无论如何,这很可能是由于应用程序级别的某种缓存,因为 mod_wsgi 本身并没有做任何事情来保留数据。

标签: python django memory-leaks mod-wsgi


【解决方案1】:

在这种情况下,您应该做的是垂直分区您的 Web 应用程序,以便它跨多个 mod_wsgi 守护进程组运行。这样,您可以根据您委派给每个 URL 子集的要求定制 mod_wsgi 守护进程的配置。由于 Django 应用程序的管理界面 URL 通常具有较高的临时内存使用要求,但不经常使用,建议这样做:

WSGIScriptAlias / /my/path/site/wsgi.py
WSGIApplicationGroup %{GLOBAL}

WSGIDaemonProcess main processes=3 threads=5
WSGIProcessGroup main

WSGIDaemonProcess admin threads=2 inactivity-timeout=60
<Location /admin>
WSGIProcessGroup admin
</Location>

所以它的作用是创建两个守护进程组。默认情况下,URL 将在进程持久存在的主守护进程组中处理。

但是,对于管理界面的 URL,它们将被定向到管理守护进程组,该进程组可以设置为具有减少线程数的单个进程,加上不活动超时,以便该进程将自动重新启动如果 60 秒后没有使用管理界面,则回收任何过多的临时内存使用。

这意味着如果自上次以来进程已被回收,则向管理界面提交请求可能会稍微变慢,因为所有内容都必须重新加载,但由于它是管理界面而不是公共 URL,这通常是可以接受的。

【讨论】:

  • 感谢您的方法。它应该定位问题。然而,我仍然对 Django 为什么不释放获取的对象感兴趣。但我会在一个单独的问题中问
猜你喜欢
  • 2013-01-12
  • 2014-12-27
  • 1970-01-01
  • 1970-01-01
  • 2015-11-26
  • 2016-02-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多