NGinx 和 Django,提供大文件 (3gb+)

NGinx & Django, serving large files (3gb+)

我在处理大文件 downloads/uploads (3gb+) 时遇到了一些问题。

因为我使用的是 Django,所以我猜提供文件的问题可能来自 Django 或 NGinx。

在我启用了 NGinx 的站点中,我有

server {
    ...
    client_max_body_size 4G;
    ...
}

在 django,我以块大小提供文件:

def return_file(path):
        filename = os.path.basename(path)
        chunk_size = 8192
        response = StreamingHttpResponse(FileWrapper(open(path), chunk_size), content_type=mimetypes.guess_type(path)[0])
        response['Content-Length'] = os.path.getsize(path)    
        response['Content-Disposition'] = 'attachment; filename={0}'.format(filename)
        return response

此方法使我的下载量从 600Mb~ 增加到 2.6Gb,但似乎下载量在 2.6Gb 处被截断了。我追踪错误:

2015/09/04 11:31:30 [error] 831#0: *553 upstream prematurely closed connection while reading upstream, client: 127.0.0.1, server: localhost, request: "GET /chat/download/photorec.zip/ HTTP/1.1", upstream: "http://unix:/web/rsmweb/run/gunicorn.sock:/chat/download/photorec.zip/", host: "localhost", referrer: "http://localhost/chat/2/" 

阅读一些帖子后,我将以下内容添加到我的 NGinx conf 中:

   proxy_read_timeout 300;
   proxy_connect_timeout 300;
   proxy_redirect off;

但是我用 *1 而不是 *553*

得到了同样的错误

我也认为可能是Django数据库超时,所以我补充说:

DATABASE_OPTIONS = {
    'connect_timeout': 14400,
}

但它也不起作用。 (通过开发服务器下载大约需要30秒)

PS:有人已经指出问题出在 Django 上,但我一直无法弄清楚原因。 Django 没有打印或登录任何错误!

感谢您的帮助!

不要使用 django 来传递静态内容,尤其是当它是这么大的静态内容时。 Nginx 是交付它们的理想选择。您需要做的就是在您的 nginx 配置文件中创建这样的映射:

location /static/ {
     try_files $uri =404 ;
     root /var/www/myapp/;
     gzip on;
     gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

}

/var/www/myapp/ 是您的 Django 应用程序的顶级文件夹。在其中,您将有一个名为 static/ 的文件夹,您需要使用 django manage.py 的 collectstatic 命令将所有静态文件收集到其中。

当然,您可以随意重命名这些文件夹,也可以一起使用不同的文件结构。有关如何为静态内容配置 nginx 的更多信息,请参见 link:http://nginx.org/en/docs/beginners_guide.html#static

我 运行 遇到类似的问题,在 nginx 错误日志文件中可以看到类似这样的行:

<TIMESTAMP> [error] 1221#1221: *913310 upstream prematurely closed connection 
while reading upstream, client: <IP>, server: <IP>, request: "GET <URL> HTTP/1.1",
upstream: "http://unix:<LOCAL_DJANGO_APP_DIR_PATH>/run/gunicorn.sock:
<REL_PATH_LOCAL_FILE_TO_BE_DOWNLOADED>", host: "<URL>", referrer: "<URL>/<PAGE>"

这是由于文件中的 --timeout 设置引起的

<LOCAL_DJANGO_APP_DIR_PATH>/bin/gunicorn_start 
(found at "command:" in /etc/supervisor/conf.d/<APPNAME>.conf)

在 gunicorn_start 文件中更改此行:

exec /usr/local/bin/gunicorn [...] \
--timeout <OLD_TIMEOUT> \
[...]

这设置为 300,我不得不将其更改为 1280(以秒为单位!)。 T运行使用

可以轻松处理大约 5GB 的内存而不会出现 RAM 问题
django.views.static.serve(request, <LOCAL_FILE_NAME>, <LOCAL_FILE_DIR>