是什么导致我的Django文件上载代码内存峰值?

2024-05-12 16:20:07 发布

您现在位置:Python中文网/ 问答频道 /正文

当我上传一个4.8mb的文件时,我的系统内存使用量从30mb跳到了300mb+。在

基本上,一个用户上传一个(例如)4.8mb的jpeg,然后上传到webfiction,然后存储在amazons3存储桶中。在

我想有一件事让我很痛苦,那就是我用easy_缩略图生成了3个文件,这些文件也存储在S3 bucket中。在

更新2:在这一点上,我认为我的主要问题是内存峰值,但从未释放。我要开始研究跑步gc.收集()在Photo.objects.create()已完成。看起来sorl缩略图可能是一个更好的选择,听起来它更适合于远程存储。在

更新1:我正在使用django调试工具栏并让它拦截重定向。我现在得到了一些有用的数据。它告诉我我已经执行了20个db查询(eek),但更糟糕的是(我相信)boto(我用于文件存储的东西)记录了124条消息。它看起来像是分别发送每个文件。也许这是正常的,也许不是?不管怎样,它看起来都很高。在

一旦上传了文件,内存永远不会恢复,除非我重置apache。在

这是我的模型:

from django.db import models
from easy_thumbnails.fields import ThumbnailerImageField
from django.conf import settings
import datetime
import os
import string
from django.core.urlresolvers import reverse

...

class Photo(models.Model):
    """
    A photo belongs to a user. A photo has a preview size and the original which
    is referenced when printing or generating the PDF for print.

    """
    def original_resolution(instance, filename):
        """
        Returns a path to upload the image to. The path is created with the
        website's slug and the current year. Using Amazon S3 for CDN storage

        """
        today = datetime.datetime.now()

        return 'uploads/{0}/{1}/{2}/{8}-{3}-{4}-{5}-{6}-{7}'.format(
            instance.owner.pk,
            today.year,
            today.month,
            today.day,
            today.hour,
            today.minute,
            today.second,
            clean_filename(filename),
            'original')

    def thumbnail_resolution(instance, filename):
        """
        Returns a path to upload the image to. The path is created with the
        website's slug and the current year. Using Amazon S3 for CDN storage

        """
        today = datetime.datetime.now()

        return 'uploads/{0}/{1}/{2}/{8}-{3}-{4}-{5}-{6}-{7}'.format(
            instance.owner.pk,
            today.year,
            today.month,
            today.day,
            today.hour,
            today.minute,
            today.second,
            clean_filename(filename),
            'thumbnail')

    def editor_resolution(instance, filename):
        """
        Returns a path to upload the image to. The path is created with the
        website's slug and the current year. Using Amazon S3 for CDN storage

        """
        today = datetime.datetime.now()
        return 'uploads/{0}/{1}/{2}/{8}-{3}-{4}-{5}-{6}-{7}'.format(
            instance.owner.pk,
            today.year,
            today.month,
            today.day,
            today.hour,
            today.minute,
            today.second,
            clean_filename(filename),
            'editor')

    height = models.PositiveIntegerField(blank=True)

    width = models.PositiveIntegerField(blank=True)

    owner = models.ForeignKey(settings.AUTH_USER_MODEL)

    original = ThumbnailerImageField(
        upload_to=original_resolution,
        resize_source=dict(size=(0, 3100), crop="scale", quality=99),
        height_field='height',
        width_field='width',
        verbose_name=u'Choose Photo')

    thumbnail = ThumbnailerImageField(
        upload_to=thumbnail_resolution,
        resize_source=dict(size=(0, 100), crop="scale"),
        blank=True,
        null=True)

    editor = ThumbnailerImageField(
        upload_to=editor_resolution,
        resize_source=dict(size=(0, 1000), crop="scale"),
        blank=True,
        null=True)

    def get_absolute_url(self):
        return reverse('photos:proxy_editor_image', kwargs={
            'pk': self.pk})

    def __unicode__(self):
        return "Photo #{}".format(self.pk)

...

下面是我处理上传的视图:

^{pr2}$

我被难住了,我可能只是不明白什么。帮忙吗?在

我已经为这个内存使用问题挣扎了几个月,终于把它缩小到这个范围。在

FWIW,我使用django1.6python2.7,webfiction托管,amazons3存储桶。在


Tags: 文件thetopathinstanceimporttruetoday
2条回答

这很可能与您的Apache设置(worker与prefork)有关。这个过程,不管是什么,都会吞噬掉一堆记忆,然后再也不会释放出来。我们也做了同样的事情,最后把应用程序的各个部分放在单独的wsgi进程组中,这样我们就可以防止内存量大的请求导致所有wsgi进程消耗大量内存。在

最后,我与mod\wsgi的创建者进行了一次深入的对话,结果是这个问题:Django, python, mod_wsgi and Apache worker

我用htop来诊断一些记忆繁重的进程。然后,根据我的发现,在apache中设置多个WSGIDaemonProcess指令,如下。。。在

WSGIDaemonProcess article-app processes=10 threads=5 display-name=articles user=myuser group=mygroup python-path=/home/admin/.virtualenvs/django/lib/python2.7/site-packages
WSGIDaemonProcess account-app-memory-heavy processes=2 threads=5 display-name=account user=myuser group=mygroup python-path=/home/admin/.virtualenvs/django/lib/python2.7/site-packages 

您还可以使用以下选项进行调试并可能提高性能:

^{pr2}$

在我的虚拟主机指令中。。。在

<Location /article/>
    WSGIProcessGroup articles
</Location>
<Location /account/>
    WSGIProcessGroup account
</Location>

现在你可以限制你的内存重上传到1或2个进程,并有N个其他进程来服务你的应用程序的其余部分,而不是消耗太多内存。在我们的例子中,我们的文章应用程序每个wsgi进程消耗1430万,我们的account应用程序消耗3.37亿。我们将account应用程序限制为2个进程,文章限制为10个,这将产生非常可预测的内存占用。在

这可能是因为据我所知,webfiction仍然使用过时的mod_wsgi,甚至可能是apache2.2。如果大文件以很慢的速度以小块的速度上传,则会出现问题。你可以在最新的gi.u版本中看到与之相关的Apache.gi和其他使用结果。在

相关问题 更多 >