Search code examples
pythondjangonginxwebservergunicorn

Nginx takes too long to send the network response using Django with Gunicorn


I'm developing a web application with Django, and so far everything seems ok, but I'm having a big problem with my server response, usually the first time I want to enter it takes around 20 to 40 seconds to get the response back from the server.

I'm using a Linode linux virtual machine running Ubuntu 18.04, is a very cheap plan just for now with only one core CPU, 2GB of ram and 50Gb of SSD storage, however as I'm the only one accessing the website I feel it is not correct that it takes so long to response (It just happen every time I restart nginx or gunicorn, or after some time of inactivity, after it respond it start to work with a normal speed).

I made a performance record with chrome dev tools and these were my results:

Network result

As you can see the network request took 22 seconds, and if I check the main thread I can see that chrome detects that time as idle, and the real time it takes the server to process the view is only a few milliseconds.

Chrome results

I also have my server with an SSL certificate, the config for nginx is the following:

upstream rienpaAdmin {
    server 127.0.0.1:8000 fail_timeout=0;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    ssl on;
    ssl_certificate /correct/path/certificate.crt;
    ssl_certificate_key /correct/path/certificate.key;
    server_name lodugo.com www.lodugo.com;

    client_max_body_size 4G;

    access_log /var/www/rienpaAdmin/nginx-access.log;
    error_log /var/www/rienpaAdmin/nginx-error.log;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /var/www/rienpaAdmin;
    }

    location / {
        include proxy_params;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect off; 
        proxy_buffering off;
        proxy_headers_hash_max_size 512;
        proxy_headers_hash_bucket_size 128;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

server {
    listen 80;
    listen [::]:80;

    server_name lodugo.com www.lodugo.com;
    return 301 https://$server_name$request_uri;
}

And I have a gunicorn service and socket like this:

socket:

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Service:

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

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/rienpaAdmin
ExecStart=/var/www/rienpaAdmin/adminPython/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --threads 1 \
          --bind unix:/run/gunicorn.sock \
          rienpaAdmin.wsgi:application

[Install]
WantedBy=multi-user.target

Anyone can give me a good explaination why this is happening?, I can upgrade my Linode server but I really feel that my current setup for just one user should respond very fast as it does after the first request, I have several days reading other questions but none of them really helped me to figure this out.

Just in case, I'm using Django 3.0 with a postgreSQL database

EDIT:

One of the answers says that I have two A records to different IPs, here is a screenshot of my DNS configuration of my NameCheap domain

here


Solution

  • Do you realise there are 2 A records for your domain name?

    $ dig lodugo.com
    ...
    ;; ANSWER SECTION:
    lodugo.com.             1308    IN      A       192.64.119.241
    lodugo.com.             1308    IN      A       45.56.114.74
    

    DNS servers will respond with each IP address in turn. I suspect that only one of the addresses is correct so there is a 50% chance of getting a bad address that will eventually timeout, and then may retry.

    This fits with what I have seen - Often taking a long time to connect, but once you hit the right address that will give fast responses until the DNS record reaches the end of it's TTL. At that point you have a 50% chance again.