我有一个apache webserver,我使用mod_wsgi使用flask设置了一个网站。我有几个可能相关或不相关的问题。
每次调用某个页面(运行一个执行繁重计算的函数需要2秒以上),内存会增加大约20兆字节。我的服务器开始时机器上的所有东西消耗了大约350兆字节。该服务器在htop中显示总共3,620兆字节。我多次重新加载这个页面后,服务器使用的总内存最终开始超过2,400兆字节,并停止增加。在达到这个级别之后,我无法让它消耗足够的内存以在数百页重新加载后进入交换。这是通过烧瓶或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>
在我的/ etc / apache2 / sites-available / default文件中。如果只创建了总共4个线程,那么内存似乎不应该增长那么多吗?
更新
如果我设置processes = 1个线程= 4,则一次发出两个请求时会出现看似随机的问题。一个我设置进程= 4个线程= 1,然后看似随机的问题不会发生。内存的增加仍在发生,实际上现在将一直上升到系统的最大RAM并开始交换。
更新
虽然我没有解决这个失控的RAM消耗问题,但是我的当前应用程序几个月没有出现问题。显然它并不太受欢迎,经过几天左右的时间,apache可能已经自动清除RAM或其他东西。
现在,我已经制作了另一个应用程序,它与前一个应用程序完全无关。之前的应用程序使用matplotlib生成大约100万像素的图像。我的新应用程序使用matplotlib生成2000万像素图像和100万像素图像。现在,当使用新应用程序生成20万像素图像时,问题变得越来越大。在整个交换空间被填满之后,某些东西似乎被杀死了,并且在有一些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(或者我使用它的方式),而不是烧瓶或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
摆脱RAM泄漏的技巧是运行
plt.close('all')
在BigComputation()中,否则,BigComputation()将在每次调用函数时保持累积RAM。我不知道我是不是只是不恰当地使用matplotlib或者编码技术不好,但我真的认为一旦BigComputation()返回,它应该释放除了任何全局对象或它返回的对象之外的所有内存。在我看来,matplotlib必须以不恰当的方式创建一些全局变量,因为我不知道它们的名称是什么。
我想我的问题现在在哪里,为什么我需要plt.close('all')?我还需要尝试Graham Dumpleton的建议,以便进一步诊断我的apache配置,看看为什么我需要在apache中设置threads = 1以使随机错误消失。
答案 0 :(得分:0)
显然是一个编程问题,但通过运行多进程配置会变得更糟。读:
也许也可以观看:
他们解释了需要注意如何设置Apache。
更新1
根据您添加的配置,您将丢失:
WSGIProcessGroup website
您的代码甚至不会在守护程序进程组中运行。因此,无论您使用何种MPM以及它正在运行多少个进程,您都会受到怜悯。
更新2
您的目录块错误。它不是指目录。应该是:
<Directory /web>
WSGIProcessGroup website
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
不需要WSGIScriptReloading指令,因为这是默认设置。
更新3
由于您没有提供确切的配置,因此我们现在无法确定您所提供的内容是相同的,为了绝对确认您正在使用守护程序模式,因此只有最多2个进程,请执行以下测试:
你想得到'网站'和''。意思是守护进程模式和主要解释器。
我们知道我们实际上只谈论两个守护进程的内存使用情况。