development and systems administration

June 15, 2012 3:09 pm

5 reasons to add Nginx to your LAMP stack now

The web has continued to grow at ever increasing speed, along with that growth comes increased demands on server response time. It’s becoming quite clear that, although Apache has been a long-standing pillar in the world of the web, it no longer makes sense as an ‘across the board’ solution to serving web pages.

This may seem completely obvious to some groups of people, while to others - Apache is still that familiar face they don’t want to part with. Then there’s the common case of having an existing infrastructure built around Apache that is, more or less, operating acceptably. You can’t justify ripping out pieces just because there exists a (possibly) better solution. In these cases small, cautious, steps are the only real way to go about changing things.

For a majority of people transition is inevitable, however - to ease the possible transition, I suggest giving Nginx a try in a very non-intrusive way: as part of your existing server setup, and not removing Apache altogether (just yet). Here are 5 reasons why you should add Nginx to your LAMP stack today.

1. It’s extremely lightweight and simple to setup

OK, so this is definitely not a major reason. After all, you shouldn’t install something just because it’s easy. However I do think a lot of people tend to avoid new things out of fear they will have to spend hours learning new concepts and configuration oddities. This is most definitely not the case with Nginx.

 I figured it would be best to mention this reason first, so that I can take you through the setup and lay the foundation.

On an Ubuntu system (12.04), setup took only a few minutes. First, install Nginx:

sudo apt-get install nginx

 For the purposes of this article, I’m going to assume you are using Nginx version 1.1.x which is what is packaged for Ubuntu 12.04, otherwise some configuration options we add may not work (like proxy_http_version).

The default configuration is fine as it is, though you will want to add some proxy directives to /etc/nginx/nginx.conf at the end of (but still inside) the http { } section

http {
    ... default config skipped ...

    # proxy settings
    proxy_redirect     off;

    proxy_http_version 1.1;
    proxy_set_header Connection "";

    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_max_temp_file_size 0;
    proxy_connect_timeout      90;
    proxy_send_timeout         90;
    proxy_read_timeout         90;

    proxy_buffer_size   128k;
    proxy_buffers   4 256k;
    proxy_busy_buffers_size   256k;
    proxy_temp_file_write_size 256k;
}

 Now, you’ll want to setup your specific site config. On Ubuntu the setup is very similar to Apache. You have your /etc/nginx/sites-available/default config file. Here’s what mine looks like:

server {
    listen       80;
    server_name  <domain_name>
    location / {;
        proxy_pass         http://127.0.0.1:8080/;
        proxy_redirect     off;
        client_max_body_size       10m;
        client_body_buffer_size    128k;
    }
}

 Remember, Nginx is going to act like a proxy. It will accept all incoming requests, and forward them to where they need to go. In this config we specify server_name as our front-facing domain name, listening on port 80. Then, for the location / directive, we specify the host & port that Apache will be listening on (I suggest localhost, port 8080).

 Finally we need to tell Apache to stop listening on port 80, and instead to listen on port 8080. We do that with an easy change to the /etc/apache/ports.conf

NameVirtualHost *:8080
Listen 127.0.0.1:8080

 I’m assuming here, you have NameVirtualHost setup. If so, make sure to also modify your site config and change the port number there as well, in /etc/apache/sites-available/default

<VirtualHost *:8080>

You’re done! Wasn’t that easy? Now just restart Apache and Nginx:

sudo /etc/init.d/apache restart
sudo /etc/init.d/nginx start

 At this point, when you visit Nginx should answer on port 80, and redirect the request to localhost:8080 which is where Apache now listens.

2. It serves static files faster

 The first tweak you can make to boost performance right away, is to set up Nginx to serve all static files for you. This takes load off Apache, as Nginx serves up static files much faster. 

 It’s extremely easy to setup, just add the following directive to your /etc/nginx/sites-available/default config file:

    # serve static files location /res  {     root    /var/www;     expires 30d;     }

 I keep all my static files in the /res directory off my webroot, but you if keep static files in several different directories, it’s easy to add multiple locations at once. For example:

    location ~ ^/(images|javascript|js|css|flash|media|static)/ {

 That directive will match any of those directories and serve their contents directly, instead of passing the request along to Apache.

Don’t forget to restart Nginx for the changes to take effect!

$ /etc/init.d/nginx restart

3. It can handle many more concurrent connections

 Nginx is very light weight and efficient. When put to the test against Apache it repeatedly outperforms, especially when it comes to handling concurrent connections.

 This means that you are helping to increase the performance of Apache, as it won’t have to handle so many concurrent connections to serve up static content like images, css and js files.

This gives you immediate savings in resources for your server, even though you’ve actually added another layer to your stack.

Apache vs Nginx benchmark

graph from http://blog.zhuzhaoyuan.com/2012/02/apache-24-faster-than-nginx/

4. It opens up new doors

 Nginx is a perfect choice for implementing things like long-polling or WebSockets. Having this proxy in place allows you to experiment with, and implement new ways to get your content to the front-end. With Nginx proxying to an asyncrhronous Python+Tornado app, you can slowly start to build stand-alone additions to your existing web application.

For example, I’ve begun implementing WebSockets for an existing large-scale LAMP application. It would be impossible to do this with Apache + the existing PHP code (which is huge). However with Nginx proxying for me, it’s dead simple to start slowly improving things with a simple Python+Tornado WebSocket app to push new events to the front-end using JSON. All I need to do is add a simple directive to my /etc/nginx/sites-available/default site conf.

    location /notify {
        proxy_pass http://127.0.0.1:8000;
        proxy_redirect off;
     }

 Once I fire up my tornado service (which should be listening on port 8000), any requests to /notify will be proxied to the tornado app, to handle any async calls I may need to carry out. This can help to speed up my existing PHP site by not only taking more load off Apache, but also allowing for smaller updates to be pushed to the user, instead of the user having to refresh to get them (or implementing some form of short-polling).

5. It makes future scaling much easier

 Let’s say you outgrow your VPC a year down the road. Already having Nginx in place will make things a lot easier on you.

 You can define groups of servers in your nginx.conf, all of which provide the same content. Then specify that group to proxy to. So, for example, you could set up another webserver with the LAMP stack, and add it to your list of servers in the nginx.conf. Now Nginx will load balance between your listed servers, the existing one and the new one.

 In this way, you can easily start to offload services until all you have left on your original server is Nginx proxying requests through to your new farm of webservers.

Scaling your LAMP stack with Nginx

image from http://scalr.net/blog/feature/2-1-feature-highlight-scale-from-one-to-many-servers/

Conclusion

I’ve always been a huge fan of Apache, but over time I’ve found myself in more varied development environments, and surprisingly I think the first performance hiccup is often not the database, or the code, but usually Apache (I have no proof to back up this claim:). This is because Apache tries to solve too many problems with one tool, and 90% of the problems it tries to address only apply to 10% of the scenarios.

The reason Nginx and Lighttpd are seeing increased usage, is because they address a few things really really well. These few things are usually all we need for a website.

What I’ve found really helps with this transitional approach, is that you can begin to test out your existing web application on Nginx, test the waters and see if everything works correctly. If so, you can eventually phase out Apache altogether (if that’s what you decide is appropriate). Alternatively, you can just leave Apache there, because the benefits of having Nginx in the stack still completely outweigh the downside of adding one more piece to the puzzle.

This theme was originally based on the Office theme by Alex Penny, with modifications by Nick Jennings

github activity