« Back to blog

Nginx, Memcached, uWsgi & Django

Alex Holt's nice article showed how to get Nginx, Memcached and Django to work together. Out of curiosity I wanted to try that setup for myself, with one modification: instead of using fastcgi to serve Django I wanted to employ uWsgi. In case you did not read the original article, he describes how to setup an environment in which Nginx directly queries Memcached for responses, which were generated and cached by Django. Only in case of cache misses is Django used to generate the result again. While surely not suitable for every usecase, it has a certain appeal to deliver computational heavy resources from a cache and directly through the webserver, minimizing overhead. I will not go into details about that here, since Alex did that very well.

Diag

Let's look at the main location handler which resides in the server-section of the Nginx config file:

location / {
            if ($request_method = POST) {
                    proxy_pass http://localhost:9004;
                    break;
            }
            default_type  "text/html; charset=utf-8";
            set $memcached_key "/your-site-name-$uri";
            memcached_pass localhost:11211;
            error_page 404 502 = /django;
    }

    location = /django  {
            proxy_pass http://localhost:9004;
            break;
    }

He uses the Memcached integration to query the key for the requested resource, which directly derives from the project and the URL which shall be retrieved. After construction of the key, he passes the request to Memached, which then returns the contents, if found. If not, we encouter an error, in which case he alters the location.

This part became tricky to replicate, with Fastcgi and the accompanying use of

proxy_pass

, we can just go ahead and pass everything on to the proxy instance. The Fastcgi config is a lot more extensive, see the article for details. So I tried to use uWsgi instead, first we have to define the django source in the server config, I use socket configuration in this instance:

 

upstream django {
    ip_hash;
    server unix:sock/uwsgi.sock;
  }

(Look here and here for details on how to setup uWsgi with Nginx and Django.) After setting it up I ended up experimenting a lot with different uwsgi_params settings, none of which produced the result I wanted. Everything messed up the process, mostly through redirect that got not handled correctly by either Nginx or Django. After some more research I finally found something interesting: named locations, which allow you to make a "symbolic" rewrite in Nginx:

error_page 404 502 = @fallback;

 

Using this kind of redirect, I could suddenly just specify the fallback handler to integrate the uWsgi part:

location @fallback {
      include     uwsgi_params;
      uwsgi_pass  django;
    }

The end result of the config file looked like this: