【问题标题】:Gunicorn timeout during file download文件下载期间的 Gunicorn 超时
【发布时间】:2019-10-17 13:03:33
【问题描述】:

我使用 nginx 作为反向代理,以便能够访问我的 Django API 并提供静态文件。 我的 Django API 正在使用 gunicorn

我有一个端点允许用户下载 csv 文件。我按照这里的说明,流式传输大型 CSV 文件:https://docs.djangoproject.com/en/2.2/howto/outputting-csv/

这里是nginx配置:

upstream docker-api {
    server api;
}

server {
    listen 443 ssl;
    server_name xxxx.com;

    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to//privkey.pem;
    include /path/to/options-ssl-nginx.conf;
    ssl_dhparam /path/to/ssl-dhparams.pem;


    location /static {
        autoindex on;
        alias /static/;
    }

    location /uploads {
        autoindex on;
        alias /uploads/;
    }

    location / {
        proxy_pass         http://docker-api;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Host $server_name;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}

这是我用来启动 gunicorn 服务器的命令:

gunicorn my_api.wsgi -b 0.0.0.0:80 --enable-stdio-inheritance -w 2 -t 180 -k gevent

当我尝试下载文件时,Gunicorn 总是在 3 分钟后超时我的请求。它不应使流式 http 响应超时。

【问题讨论】:

    标签: python django python-3.x nginx gunicorn


    【解决方案1】:

    问题在于你的 gunicorn 命令。

    我们来看看:

    gunicorn my_api.wsgi -b 0.0.0.0:80 --enable-stdio-inheritance -w 2 -t 180 -k gevent

    gunicorn 命令上的-t 代表timeout,它以秒为单位,并且您的gunicorn worker 超时,因为您已将超时设置为180 秒(3 分钟)。

    当我尝试下载文件时,Gunicorn 总是在 3 分钟后超时。

    要解决这个问题,你可以简单地增加超时时间,例如,下面的 gunicorn 命令会将超时时间设置为 5 分钟:

    gunicorn my_api.wsgi -b 0.0.0.0:80 --enable-stdio-inheritance -w 2 -t 300 -k gevent

    查看文档了解更多信息:http://docs.gunicorn.org/en/stable/settings.html#timeout

    【讨论】:

    • 但是如果文件耗时超过 5 分钟怎么办?有没有办法避免在流式 http 连接期间超时?我知道 Gunicorn 在 3 分钟后每隔一个请求都会超时,但它不应该让流式请求超时
    • 然后你必须设置一个单独的 gunicorn 实例运行相同的应用程序或一个单独的应用程序提供具有不同超时的文件。附带说明一下,如果您从硬盘驱动器提供文件,那么可能没有理由使用 Django,也许您可​​以直接使用 nginx 提供服务?
    • 没有办法说如果请求是Streaming Http请求那么超时就不适用了?
    • 据我所知,没有办法做到这一点。我也遇到了 Gunicorn 超时问题,因为我的 Flask 路由需要很长时间才能返回,所以我最终改用了 Redis Queue (python-rq)。
    【解决方案2】:

    此错误通常由两件事引发:

    1. Nginx 超时:你应该在其中添加这两行代码 Nginx 文件:

      • 首先,转到您在以下目录中创建的文件(在我的例子中名为myproject

    $ nano /etc/nginx/sites-available/myproject

    • 文件的location / 部分应如下所示:(注意 超时部分):

    location / {
            include proxy_params;
            proxy_pass http://unix:/run/gunicorn.sock;
            proxy_connect_timeout 300s;
            proxy_read_timeout 300s;
        }
    • 然后重启 Nginx:

    $ systemctl 启动 nginx

    1. gunicorn 超时:转到确切的目录:

    $ nano /etc/systemd/system/gunicorn.service

    • --timeout 300 添加到文件的[service] 部分下。如需更多帮助,请参阅link 下方的整个文件:

    [Unit]
    Description=gunicorn daemon
    Requires=gunicorn.socket
    After=network.target
    
    [Service]
    User=sammy
    Group=www-data
    WorkingDirectory=/home/sammy/myprojectdir
    ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn \
              --access-logfile - \
              --workers 3 \
              --timeout 300 \
              --bind unix:/run/gunicorn.sock \
              myproject.wsgi:application
    
    [Install]
    WantedBy=multi-user.target
    • 接下来,重启 gunicorn:

    $ systemctl daemon-reload

    $ systemctl restart gunicorn.socket gunicorn.service

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-27
      相关资源
      最近更新 更多