Rolling Out a New Backend

The big limitation of my old webhost was the lack of control I had over the backend. It was great at php, and had some python support, but didn’t even give me command-line access. Lately I’ve been playing with ruby on rails a lot, as well as thinking about the idea of doing things like programmatically generating pdf files and other things that I wouldn’t be able to do with my old host. So I’ve switched to Slicehost. Now I get to run the entire backend myself, which meant some choices.

First, I’m using nginx as the web server instead of apache. This is because the event-driven architecture of nginx is much better than apache at handling the massive traffic that my website gets. Ok, but seriously, nginx does do some things that make me like it.

Unlike Apache, it doesn’t try to do everything itself. It delegates dynamic page generation (that is, python, php, ruby, etc) to other processes over a socket or to a server listening locally on another port. For example, I get php support using FastCGI with the php5-fpm ubuntu package. php5-fpm listens on port 9000, and nginx forwards php requests (locally) to this server.

For python web services, I’m using uWSGI as a WSGI server. Again, nginx forwards python requests over a socket to uWSGI, which manages the python interpreter and responds to a request. This approach differs from other WSGI server implementations that double as web servers; performance-wise, this approach pays off, as this benchmark shows. Support for Ruby and other web languages can be added similarly.

Another advantage of separating the webserver from the interpreter is that it allows the interpreter to be restarted (to roll out a new version of a script) without the webserver going down.

Configuring nginx to do this isn't hard: here's the relevent part form my nginx config: