Hi all,

I have this weird problem: REST API response is not returned to callers
correctly. It can only be recreated under some situation. Maybe it is a
caching problem, or incorrect configurations, or bug somewhere (???)

The configuration is Nginx<->uWsgi<->Django Rest Framework (DRF) under
Ubuntu.

I will summarize the business logic and the problem:
=========================================
All REST APIs are protected by Basic Authentication (username/password info
is persisted in Postgres)
DRF gets the authentication header and does the authentication itself.
There is a POST REST API "login" ; it returns a response with the user
information (like username).
There are other REST APIs, and say one of them is  POST API called "XXX".

To recreate the problem:
====================
Client(the tool Postman) calls "login" API with user "A" authentication.
Response is good with user "A" info; response is 200 (as expected)
Client calls "XXX" API with user "B". It returns 500 (as expected).
Client calls "login" again repeatedly with user "A" authentication; now we
see intermittent problem; sometimes the returned response is about user
"A", but sometimes it is about user "B". Correct answer should be always
about user "A". All responses are 200.

My investigation:
==============
When the problem happens, if I look at the Nginx logs, I can see the new
entries with response status 200 but when I look at the Django logs, I
don't see the new entries. Based on this observation, I think Django is
being skipped somehow. Maybe uWsgi is being skipped as well. Maybe Nginx is
caching some response for certain situation. But it seems all is triggered
by the 500 response.

Any debugging tips is appreciated. I am just looking for new idea on how to
approach the problem.

Thanks in advance.

Steve

Below is configuration details:
========================

Ubuntu 16.04 LTS

uWSGI (2.0.14)

Django (1.9.12)

djangorestframework (3.3.3)

nginx version: nginx/1.10.0 (Ubuntu)


===========nginx.conf====================
user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
        worker_connections 768;
        # multi_accept on;
}

http {

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        # server_tokens off;

        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##

        gzip on;
        gzip_disable "msie6";

        log_format auth
           'http_authorization= "$http_authorization" '
           'request= "$request" '
           'time_local= "$time_local" '
           'status= "$status" '
           ;

        ##
        # Virtual Host Configs
        ##

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}

============nginx default file===================
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        server_name _;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                #try_files $uri $uri/ =404;
                try_files $uri $uri/ /index.html;
        }
}

============nginx config file for django================
# the upstream component nginx needs to connect to
upstream django {
    # we will be using socket connection
    server unix:///tmp/zlims_uwsgi.sock;
}

# configuration of the server
server {

    # use this version to receive all requests
    listen 8000 default_server;

    # the domain name it will serve for
    # server_name _;
    charset     utf-8;

    # server root, any location block path will be relative to this root
    root /opt/zlims;

    # max upload size
    client_max_body_size 75M;   # adjust to taste

    # Django media
    location /media  {
        #alias /opt/zlims/media;  # your Django project's media files -
amend as required
    }

    location /static {
        alias /opt/zlims/be/static/; # your Django project's static files -
amend as required
    }

    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  django;
        #include     /opt/zlims/uwsgi_params; # the uwsgi_params file you
installed
        include      uwsgi_params; # the uwsgi_params file you installed

        proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;
        proxy_cache_bypass $http_pragma    $http_authorization;
        proxy_no_cache $cookie_nocache $arg_nocache$arg_comment;
        proxy_no_cache $http_pragma    $http_authorization;

        access_log /var/log/nginx/auth.log auth;
    }
}

========= uwsgi_params file======================
uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;

=============uwsgi vassel .ini file=====================
[uwsgi]

set-placeholder = base_dir = /opt/zlims/be

chdir        =/opt/zlims/be
module       =zlims.wsgi
home        =/opt/zlims/venv

master       =true
processes    =10

socket       =/tmp/%n.sock
chmod-socket =666
vacuum       =true
daemonize    =/var/log/zlims/uwsgi_zlims.log
logdate      =%%d/%%m/%%Y %%T
log-maxsize  =10000000
disable-logging =true          # disable request logging

lazy-apps          =true
single-interpreter =true
enable-threads     =true

========uwsgi service script (for systemd) ===========================

# uwsgi service script

[Unit]
Description=uWSGI Emperor service
After=syslog.target

[Service]
ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals/
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all

[Install]
WantedBy=multi-user.target
_______________________________________________
uWSGI mailing list
uWSGI@lists.unbit.it
http://lists.unbit.it/cgi-bin/mailman/listinfo/uwsgi

Reply via email to