Performance improvement with nginx/Apache combination

17 August 2009

Ever since I set up this web server, I have been toying with the idea of running two web servers: a lightweight one to handle static content, with Apache running as a backend serving php and other dynamic content. A number of articles said it would boost performance, especially on sites with a high load, and because my site is small I thought it would be a pointless optimization.

However, I have just implemented nginx as a front end server which will serve static content (such as images, css, html) with Apache as a back end server handling PHP and other scripts.

There is a significant difference in performance. The Drupal sites all seem to be running much quicker now, presumably because the Apache processes are not bogged down handling image and css requests.

It has also meant I can tune Apache to handle less requests, so Apache is now using less memory (which is important on a VPS with only 256 MB of RAM). I was frequently hitting the limit and using the swap space (which of course is slower!), so this is a welcome benefit.

Now, just like I did with the Drupal set of articles, I am going to write about how I set it up, because the documentation on the net is somewhat hazy.

First off, I installed nginx with the sudo apt-get install nginx command.

Then came the configuration. So I opened up the /etc/nginx/nginx.conf file and began editing. Obviously, as I only wanted to be testing, I changed listen 80 to listen 81.

Then, I needed to create an upstream server where dynamic requests would be forwarded to. To do that, in the http block, I added:

upstream apache {
    server 127.0.0.1:80;
}

Obviously, as Apache was still running on port 80 at that point, I set it to use port 80.

In the server block, I then set the appropriate settings and added the following code configuration lines.

location ~ (js|css|gif|jpg|jpeg|png|htm|html|txt|rar|zip|exe|tgz|tar.gz|tar|gz)$ {
    expires 30d;
}

location / {
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://apache;
    proxy_redirect default;
}

The first location block checks for static files, such as image, html, text, javascript and other downloads. It will then set the expire header to 30 days, so that they do not need to be redownloaded all the time.

The second block handles everything else (i.e. non-static files). These need to be forwarded onto apache. As my site uses virtual hosts, I set the host header and also the X-Real-IP and X-Forwarded-For headers. These are used by Apache so it knows who the real client is, and doesn't assume that it is in fact 127.0.0.1.

The final step was to set up Apache so it knew the real client's IP address. To do this, I used a third party module called mod_rpaf (http://stderr.net/apache/rpaf/).

Installing it was fairly simple, even though it doesn't have a Debian package. I had to install apache2-threaded-dev for the axps command, which was another simple apt-get.

Then I just needed to build and install it for Apache 2.0, and to do so I executed these commands:

make rpaf-2.0
make install-2.0

After that, the final thing to do was to add the appropriate configuration. This was enough to get it working:

LoadModule rpaf_module /path/to/rpaf.so
RPAFenable On
RPAFsethostname On
RPAFproxy_ips 127.0.0.1
RPAFheader X-Forwarded-For

Once I'd finished it and tested it, I simply swapped around the ports. Apache was changed to run on 8080, nginx on 80 and nginx would forward to 8080. After a reboot, it all seems to be running nicely!

 

Comments

Nobody has commented on this post yet.

Add comment

If you wish, you can add a comment.