python - default_storage.exists 极其缓慢且经常超时

标签 python django amazon-s3 django-storage

我们刚刚将一个 Django 项目迁移到 Heroku,并将我们所有的媒体和静态文件放在 Amazon S3 上(使用 django-storages 和 s3-boto)。

尽管我听说 Amazon S3 速度非常快,而且在性能低下时结果很少,但我们的图像加载速度已经减慢到绝对爬行速度并且经常超时。超时代码的一个例子是我们的一个模型的这个属性,它试图选择一个合适的图像,最终回落到返回 None:

@property
def photo(self):
    """Transparently serve the best available image for templates"""
    if self.model_shot.storage.exists(self.model_shot.name):
        return self.model_shot
    elif self.image.storage.exists(self.image.name):
        return self.image
    else:
        return None

当我在一个导致问题的模型上进行测试时,我试过这个:

$ heroku run python manage.py shell
...
>>> design = Design.objects.get(pk=10210)
>>> design.photo

此命令导致 shell 在最终返回 ImageFieldFile 对象之前挂起几秒钟。对它的后续调用会立即返回,这让我相信结果已缓存。

我的问题是,处理此问题的最佳方法是什么?我听说过很多关于在这种情况下使用 CloudFront 的信息,但这绝对不是因为高流量(我们网站上基本上不应该有任何流量)。其他一些缓存框架?完全不同的东西?

大多数有问题的图像至少为 1000x1000 像素。

最佳答案

切换到 CloudFront 完全解决了这个问题,而且相对容易(没有代码更改只是在 Amazon 控制台上胡闹),所以我决定回答我自己的问题。

tl;dr 不要直接从 S3 提供文件;设置 CloudFront。


通过 CloudFront 提供 S3 存储桶

第 0 步:如果您还没有,请确保您的存储桶名称符合 "best practices"用于命名桶。他们不一定在所有应该的地方都让这一点显而易见,但是一个糟糕的存储桶名称可能会完全破坏它与其他 Amazon Web 服务的互操作性。最好的做法是将您的存储桶命名为不太长的全小写字母(<= 60 个字符左右)。

第 1 步:为了让 CloudFront 提供存储桶中的文件,您需要将其设置为提供静态网站。您可以通过存储桶的 Permissions 选项卡在 Amazon AWS 控制台上执行此操作。亚马逊有几个地方有这方面的说明/文档; IMO 最清楚的是 these . 重要:确保将默认根对象设置为 index.html——该文件甚至不必存在,但设置

第 1.5 步 [可能是可选的]:确保您的存储桶的权限正确。尽管我从 S3 提供文件没有问题,但更改为 CloudFront 来提供它们将所有内容都变成了 403:禁止访问 错误。如果有疑问,并且您的文件不敏感,您可以在 AWS 控制台中右键单击存储桶的文件夹,然后单击 Make Public警告:这可能是一个非常耗时的过程,出于某些愚蠢的原因(即使是在服务器端),您的浏览器 session 必须保持打开。首先执行此操作,不要关闭您的 session 。对于我们的存储桶,这大约需要 16 个小时。 :/

第 2 步:转到 AWS 控制台中的 Amazon CloudFront 部分,然后单击 Create Distribution 按钮。将其设为 Web 分发(默认)并使用您在上一步中通过为静态 Web 分发设置存储桶而生成的域作为源。同样,国际海事组织,these是 AWS 文档中最清晰、最直接的说明。您可以在此处保留几乎所有默认设置。创建后,只需等待它在控制台上列为“已部署”即可。

第 3 步:将您的应用配置为从 CloudFront 而不是 S3 提供服务。这是最简单的部分,因为 URL 已从 https://bucketname.s3.amazonaws.com/path 透明地移动到 https://somerandomstring.cloudfront.net/path(奖励:您可以将后者设置为 CNAME 记录以指向类似 media.yourdomain.tld 的内容;我们没有这样做所以我不会这样做在这里进入)。由于我将 Django 与 django-storagess3-boto 结合使用,所以这最终变成了 setting up that Cloudfront domain in settings.py 的简单问题。 :

AWS_S3_CUSTOM_DOMAIN = 'd2ynhpzeiwwiom.cloudfront.net'

就是这样!通过这些更改,我们所有的速度问题都消失了,我们的富媒体页面(每页 6-20 MP 图像)突然加载速度比以往任何时候都快!

关于python - default_storage.exists 极其缓慢且经常超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24685790/

相关文章:

amazon-web-services - 在我的 html 中显示 AWS 认知池 ID 是否安全?

python - 在不打开 Pythonwin 的情况下运行 Python 脚本

Django Rest Framework 所有者权限

python - 从字符串中删除变音符号以实现搜索功能

django - 搜索查询集的 __contains 过滤器有用吗?

ruby-on-rails - 使用Carrierwave从S3下载图像(无需打开)

python - 如何在Python中过滤掉具有特定字符串的多列

python - 如何在测试的不同 python 源中模拟导入?

python - 如果可以向元组添加 (a += (3,4)),那么元组如何不可变

ruby-on-rails - 如何在 ruby​​ on rails 中写入 tmp 文件或将图像对象流式传输到 s3