首页 > 解决方案 > 如何减少分叉进程以运行可执行文件的 Web 服务器的内存使用量?

问题描述

我有一个运行在具有 1GB RAM 的 AWS EC2 实例上的 Django Web 服务器。当向 Web 服务器发出某个请求时,我需要使用subprocess.call('./executable'). 可执行文件运行一个 Perl 脚本,该脚本执行一些文件 I/O,然后对从文件解析的数据进行一些计算,没什么太疯狂的。

我开始遇到内存分配问题,导致我的 Web 服务器崩溃,所以我搞砸了对分配给每个子进程的虚拟内存设置硬限制,使用ulimit -v some_value. 我发现每个子进程需要大约 100MB 才能运行而不会出错,因此我遇到只有 1GB RAM 的内存问题也就不足为奇了。

不过,我想知道为什么这种内存使用率如此之高。是否因为我subprocess.call从运行内存密集型 Web 服务器的进程调用而分配了大量额外内存?运行一个运行 Perl 脚本的可执行文件是否必然会占用大量内存,因为 Perl 有一些开销或其他东西?如果 Perl 脚本用 Python 重新编写并直接在 Django Web 服务器中运行,它会使用更少的内存吗?

非常感谢对此提供的任何帮助。谢谢!

标签: pythondjangoperlsubprocessout-of-memory

解决方案


比我更了解内核、进程和内存的细节的人发表了一些很棒的评论!去看一下。

我真的没有给你一个明确的答案,但我希望在这里能有所启发:

这个 SO anwer 解释了内存使用的原因以及内存不足异常: Python memory allocation error using subprocess.Popen 。

这是 Unix 中很常见的问题,实际上与 python 或生物信息学无关。对 os.fork() 的调用暂时使父进程的内存翻倍(父进程的内存必须对子进程可用),然后将其全部丢弃以执行 exec()。虽然实际上并不总是复制此内存,但系统必须有足够的内存来允许它被复制,因此如果您的父进程正在使用超过一半的系统内存并且您的子进程甚至"wc -l ",你会遇到内存错误。

您应该考虑在 Python 中实现这个 perl 脚本并在您的视图中使用该模块/包,避免在您的请求-响应周期中使用另一个线程/进程来处理这个问题。

另一件可能相关或不相关的事情,如果这是一项长时间运行的作业或 CPU 密集型任务,您应该考虑使用CeleryPython RQ之类的东西在后台作业中处理它。这样可以使您的服务器快速响应请求并避免请求积压,从而避免出现 20 个请求仍在处理的情况,因为这个长时间运行的任务正在完成它的工作,因此没有其他人可以访问服务器。使用工人的选择将取决于您的需求、截止日期等。


推荐阅读