0

Problem

Receive 502 bad gateway when i try to execute a django management command via gunicorn

Logic Line

I think the problem is about permissions, something like gunicorn is not able call the command. I say that because i can run it locally where i don't use gunicorn.

I can run it in these two methods:

  • python manage.py runserver and after that, fire it using Postman and that's ok.

  • The second one is calling by terminal python manage.py command_name and that's ok also.

  • On production, i'm also able to run with python manage.py command_name. But not by postman, because it return 502 (the main problem)

PS. If i remove call_command it returns 200 ok, so, it seems like the core problem is the execution of this command.

The code

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 sample

<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 Conf

[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 Log error

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"

What i've tried

  • sudo chown -R www-data:www-data /var/www/project
  • sudo chown -R ubuntu:ubuntu /var/www/project
  • Change my Environment value on gunicorn config based on this question solution: Django call_command permissions nginx+gunicorn+supervisord. Adding PYTHONPATH, but this guy use it on supervisor config, this project don't use supervisor, so i tried to put it on gunicorn file, it was just a try.
Marcos Mendes
  • 1,091
  • 1
  • 8
  • 15

1 Answers1

0

I realized it was a problem of timeout

The default timeout of gunicorn is 30 seconds based on its documentation.

Doc. Workers silent for more than this many seconds are killed and restarted.

My request get more than 30 seconds, so, gunicorn killed the process and nginx returned 502.

Solution

  • Change gunicorn default timeout
  • Change nginx timeout

Gunicorn

I added the timeout option to gunicorn ExecStart line

--timeout 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

Added this option to HTTP part of nginx conf

proxy_read_timeout 300s;

Restarted nginx and gunicorn and that's worked like a charm

Marcos Mendes
  • 1,091
  • 1
  • 8
  • 15