Python Django call_command 权限 gunicorn+nginx

Python Django call_command permissions gunicorn+nginx

问题

当我尝试通过 gunicorn 执行 django 管理命令时收到 502 错误网关

逻辑线

我认为问题出在权限上,像 gunicorn 这样的东西无法调用命令。我这么说是因为我可以在不使用 gunicorn 的地方 运行 它。

我可以运行这两种方法:

PS. 如果我删除 call_command 它 returns 200 ok,那么,核心问题似乎是执行这个命令。

密码

class TestCommandView(views.APIView):
    def post(self, request):
        id = request.data['id']

        try:
            call_command('command_name', target_id=id)
            return Response({"status": "success"})
        except Exception as error:
            return Response({"status": "error: " + str(error) })

Return样本

<html>
    <head>
        <title>502 Bad Gateway</title>
    </head>
    <body bgcolor="white">
        <center>
            <h1>502 Bad Gateway</h1>
        </center>
        <hr>
        <center>nginx/1.14.0 (Ubuntu)</center>
    </body>
</html>

Gunicorn 大会

[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=ubuntu
Group=www-data
RuntimeDirectory=gunicorn
WorkingDirectory=/var/www/project
ExecStart=/var/www/project/venv/bin/ddtrace-run /var/www/project/venv/bin/guni$
Environment="DJANGO_SETTINGS_MODULE=project.settings.prod"

[Install]
WantedBy=multi-user.target

Nginx 日志错误

2019/03/13 13:43:38 [error] 27552#27552: *3128 upstream prematurely closed connection while reading response header from upstream, client: IP, server: api.project.com, request: "POST /api/project/endpoint/ HTTP/1.1", upstream: "http://unix:/tmp/project.sock:/api/project/endpoint/", host: "api.project.com"

我试过的

发现是超时的问题

根据其文档,gunicorn 的默认超时为 30 秒。

Doc. 停止运行超过此秒数的工人将被杀死并重新启动。

我的请求超过了 30 秒,所以,gunicorn 终止了进程,nginx 返回了 502。

解决方案

  • 更改gunicorn默认超时
  • 更改 nginx 超时

独角兽

我将超时选项添加到 gunicorn ExecStart

--超时300

    ExecStart=/var/www/project/venv/bin/ddtrace-run /var/www/project/venv/bin/gunicorn --bind unix:/tmp/project.sock project.wsgi:application --access-logfile /home/ubuntu/gunicorn.log --error-logfile /home/ubuntu/gunicorn.error.log --timeout 720 --workers 3

Nginx

将此选项添加到 nginx conf 的 HTTP 部分

proxy_read_timeout 300s;

重新启动 nginxgunicorn 并且效果很好