python - apache上的python flask应用程序的随机问题

标签 python apache memory matplotlib flask

我有一个apache webserver,我用flask使用mod_wsgi建立了一个网站。我有几个问题可能是相关的,也可能不是相关的。
每次调用某个页面(运行一个执行超过2秒的繁重计算的函数)时,内存会增加大约20兆字节。我的服务器一开始就被机器上的所有东西消耗了大约350兆字节。服务器总共有3620兆字节显示在htop中。在我多次重新加载这个页面之后,服务器使用的总内存最终开始超过2400兆字节,不再增加那么多。当它达到这个级别后,我无法让它消耗足够的内存,以便在数百次页面重新加载后进行交换。这是由flask、apache或python设计的吗?对我来说,如果有某种缓存机制,如果每次调用同一个URL,似乎不会发生内存累积。如果我重新启动apache,就会释放内存。
有时对此页的调用会导致被调用函数出错,即使它们都是只读调用(不向磁盘写入任何数据),并且每个页的查询字符串都是相同的。
我有另一个页面(调用另一个计算量小得多的函数),当与web服务器上运行的其他页面同时调用时,会随机出错,或者结果(图像)意外返回。
问题2和3是否与问题1有关?问题2和3可能是由于错误的编程或机器内存造成的吗?我可以通过在大约40个firefox标签中加载相同的URL,然后选择“重新加载所有标签”选项来重现随机性。
为了得到更好的答案,还应该提供哪些信息?
我试过放置

import gc
gc.collect()

输入我的密码。
我确实有
    WSGIDaemonProcess website user=www-data group=www-data processes=2 threads=2 home=/web/website
    WSGIScriptAlias / /web/website/website.wsgi
    <Directory /web/website>
            WSGIProcessGroup website
            WSGIScriptReloading On
            WSGIApplicationGroup %{GLOBAL}
            Order deny,allow
            Allow from all
    </Directory>

在my/etc/apache2/sites available/default文件中。如果只创建了4个线程,内存似乎不会增长那么多,是吗?
更新
如果我设置processes=1threads=4,那么当同时放置两个请求时,看起来随机的问题就会一直出现。如果我设置进程=4个线程=1,那么看起来随机的问题就不会发生。不过,内存的增加仍在发生,实际上现在将一直增加到系统的最大RAM,并开始交换。
更新
虽然我还没有解决这个失控的RAM消耗问题,但我的当前应用程序已经几个月没有问题了。显然它并不太流行,几天后,apache可能会自动清除RAM或其他东西。
现在,我制作了另一个应用程序,它与前一个应用程序完全无关。上一个应用程序使用matplotlib生成了大约100万像素的图像。我的新应用程序正在使用matplotlib生成2000万像素图像和100万像素图像。当使用新应用程序生成2000万像素的图像时,问题变得更大了。在整个交换空间被填满之后,一些东西似乎会被杀死,并且在有一些可用的RAM和交换空间的情况下,事情会以一个不错的速度工作一段时间,但是当RAM被消耗时,运行速度会慢得多。以下是正在运行的进程。我认为没有任何额外的僵尸进程在运行。
$ ps -ef|grep apache  
root      3753     1  0 03:45 ?        00:00:02 /usr/sbin/apache2 -k start  
www-data  3756  3753  0 03:45 ?        00:00:00 /usr/sbin/apache2 -k start  
www-data  3759  3753  0 03:45 ?        00:02:06 /usr/sbin/apache2 -k start  
www-data  3762  3753  0 03:45 ?        00:00:01 /usr/sbin/apache2 -k start  
www-data  3763  3753  0 03:45 ?        00:00:01 /usr/sbin/apache2 -k start  
test      4644  4591  0 12:27 pts/1    00:00:00 tail -f /var/log/apache2/access.log  
www-data  4894  3753  0 21:34 ?        00:00:37 /usr/sbin/apache2 -k start  
www-data  4917  3753  2 22:33 ?        00:00:36 /usr/sbin/apache2 -k start  
www-data  4980  3753  1 22:46 ?        00:00:12 /usr/sbin/apache2 -k start  

当我看htop时,我有点困惑,因为它显示的过程比top或ps多得多。
更新
我发现内存泄漏是由于matplotlib(或我使用它的方式)造成的,而不是flask或apache,因此我最初发布的问题2和3确实是问题1的单独问题。下面是我在ipython中为消除/重现问题而制作的一个基本函数。
def BigComputation():
    import cStringIO
    import matplotlib
    matplotlib.use('Agg')
    import matplotlib.pyplot as plt

    #larger figure size causes more RAM to be used when savefig is run.
    #this function also uses some RAM that is never released automatically
    #if plt.close('all') is never run, but it is a small amount,
    #so it is hard to tell unless run BigComputation thousands of times.
    TheFigure=plt.figure(figsize=(250,8))

    file_output = cStringIO.StringIO()

    #causes lots of RAM to be used, and never released automatically
    TheFigure.savefig(file_output)

    #releases all the RAM that is never released automatically
    plt.close('all')

    return None

消除内存泄漏的诀窍是运行
plt.close('all')

在bigcompulation()中,否则bigcompulation()只会在每次调用函数时不断累积RAM。我不知道我是在不恰当地使用matplotlib还是使用了错误的编码技术,但是我真的认为一旦bigcompulation()返回,它应该释放所有的内存,除了任何全局对象或返回的对象。在我看来,matplotlib一定是以不恰当的方式创建了一些全局变量,因为我不知道它们的名称。
我想我现在的问题是为什么我需要plt.close(“all”)?我还需要尝试Graham Dumpleton的建议,以便进一步诊断我的apache配置,了解为什么我需要在apache中设置threads=1以消除随机错误。

最佳答案

显然是一个编程问题,但运行多进程配置会使情况更糟。阅读:
http://blog.dscpl.com.au/2012/10/why-are-you-using-embedded-mode-of.html
也可以看看:
http://lanyrd.com/2012/pycon/spcdg/
http://lanyrd.com/2013/pycon/scdyzk/
它们解释了如何设置Apache需要小心。
更新1
根据您添加的配置,您缺少:

WSGIProcessGroup website

您的代码甚至不会在守护进程组中运行。因此,无论您使用的是什么MPM,以及它运行的进程有多少,您都将受到影响。
更新2
你的目录块错误。它不是指目录。应该是:
<Directory /web>
        WSGIProcessGroup website
        WSGIApplicationGroup %{GLOBAL}
        Order deny,allow
        Allow from all
</Directory>

不需要WSGIScriptReloading指令,因为这是默认的。
更新3
因为你没有提供你的精确配置,所以我们现在不能确定你所给予的是相同的,绝对确认你使用守护进程模式,因此只有最大2个进程,在以下测试:
http://code.google.com/p/modwsgi/wiki/CheckingYourInstallation#Embedded_Or_Daemon_Mode
http://code.google.com/p/modwsgi/wiki/CheckingYourInstallation#Sub_Interpreter_Being_Used
你想得到'网站'和'。意思是守护进程模式和主解释器。
我们知道我们实际上只是在讨论两个守护进程的内存使用情况。

关于python - apache上的python flask应用程序的随机问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16428132/

相关文章:

python - 如何将 Pandas 系列字符串转换为包含 1970 年之前日期的非标准格式的 Pandas 日期时间

objective-c - 为什么 NSColorPanel 交互会累积内存?

java - 在jsp中添加一个类

php - Laravel 在主页上显示 index.php 的代码

java - 从集群中获取现有的 mapreduce 作业(作业可能正在运行或已完成)

java - 如何在应用程序崩溃之前捕获 OutOfMemoryError?

php - 是什么导致 PHPExcel 在使用分块过滤器读取文件时使用如此多的内存?

python - Vim:在 Python 源文件中获得自动缩进,但没有智能缩进

python - 如何等待生成的线程在 Python 中完成

python - "safe"python HTML 文本格式(ala textile)