Load Balancing for TurboGears using Nginx
Filed under: nginx turbogearsI decided to test out Nginx's load-balancing capabilities. Turns out to be remarkably easy.
CherryPy is not a fast HTTP server (CP3 is supposedly at least twice as fast, but not released yet, and either way, TurboGears is currently tied to CP2). That's okay, but there are some things you can do to make sure that it doesn't become a bottleneck for your TurboGears website.
The first and obvious thing is to serve static files (images, javascript, css, etc) from a regular webserver. Lots of people use Apache or Lighttpd for this purpose. A few others (including myself) prefer to use Nginx.
This solves a lot of the performance issues right off the bat. However there's another technique that can help quite a bit as well: load balancing.
Nginx provides a simple and elegant way to load balance across two or more backend servers. Here's how you do it with TurboGears.
The TurboGears Setup Edit your prod.cfg file and add/change the following lines to look like:
server.socket_host="127.0.0.1" server.socket_port=8000
Next, copy your prod.cfg file to a file called prod2.cfg and edit it with the following:
server.socket_host="127.0.0.1" server.socket_port=8001
Next, start two TurboGears instances:
./start-myproject.py prod.cfg& ./start-myproject.py prod2.cfg&
The Nginx Configuration The next step is to edit your Nginx configuration and add the following:
upstream myproject {
server 127.0.0.1:8000;
server 127.0.0.1:8001;
}
server {
listen: 80;
server_name: www.domain.com;
location / {
proxy_pass http://myproject;
}
}
Now restart Nginx.
Unbelievably, that's it. If you want to see the effects (and convince yourself it works), you can change your dev.cfg files in the same fashion (probably from two separate terminals) and click through your site like mad (or wget it) and watch as each TurboGears backend takes part of the load.
A couple things to note:
- Sessions appear to work fine. I've used this technique with Identity and it doesn't appear to matter which backend the request goes to.
- This probably won't work with SQLite. SQLite is not meant for concurrent access and running two TG servers against the same database is going to be a problem. Besides, if you are doing load balancing, why are you using a toy database anyway? ;-)






