Apache子进程在分配大块内存后没有释放内存

3
我在CentOS上使用WSGI运行Django 1.4,Apache是Prefork但未配置为守护进程模式,启动了8个子进程。我执行了一个数据库查询,使其中一个子进程(正在处理请求的那个)的Resident Memory大小从100 MB增加到了555 MB。在我的代码中,我使用pyodbc游标获取行数据,但数据没有被存储在任何地方,例如全局变量中。

我向服务器发送一个JSON响应来返回序列化数据。此时,我希望Resident Memory回到100 MB,但它仍然是555 MB。
随后的查询不会增加内存占用大小(它保持在555 MB),这让我推测这不是内存泄漏,而是子进程没有释放内存。

同时,在Windows上使用Django嵌入式开发服务器执行相同的步骤会导致内存大小增加到500 MB,但会恢复到低于100 MB。

有什么想法吗?
1个回答

2
我建议您观看以下内容:并注意在其中提到的Apache的MaxMemFree指令。听起来你可能正在将一个非常大的响应作为一个字符串返回,并且使用了任何Apache输出过滤器,这会导致Apache在处理它时重复使用内存。如果您使用的是没有MaxMemFree限制的Apache 2.2,那么可以扩大Apache内存池的大小,而内存不会被回收。 如果问题是响应大小,那么也许可以让JSON编码器在构造响应时将其流式写入文件,然后再将文件内容流式传输回来。如果内存使用量是因为查询数据库数据,则需要查看您如何执行查询以及是否需要所有数据。

我明天会验证一下,但我认为你可能做对了。我正在返回一个巨大的JSON响应而不是流式传输它。 - Sid
请注意,即使使用MaxMemFree,内存使用量可能仍然不会下降,因为我不确定Apache是否使用可以从高内存返回大块内存的内存分配器,就像Python一样。至少它不会在Apache内存池中保留内存,并将其返回给整个进程的空闲内存列表。从技术上讲,在Python中,您可能会遇到内存不下降的相同问题,这实际上完全取决于内存分配的顺序。直到现在,您可能只是幸运而已,事实上,这可能是您在Apache下看不到内存下降的原因之一。那就是分配的顺序。 - Graham Dumpleton
这是检索2000行数据并从该数据创建2000个对象所导致的问题。 这不是JSON,因为如果我检索数据并且没有返回任何JSON(在创建对象后立即丢弃数据),我仍然会看到内存增加。将MaxMemFree设置为256在prefork下没有任何区别。我看了你的PyCon演讲 - 不相关,但似乎你推荐使用WSGI守护程序模式与预派发MPM? - Sid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接