Why I switched to nginx
When I originally setup my VPS I didn’t think twice about using Apache for my web serving duties. Setting up the LAMP environment was very easy and everything that I needed to host worked perfectly with this setup. However, when I decided to create my blog using Rails, I knew I would have to modify my setup. Originally I had planned to use mod_proxy_balancer and mongrel, but then Phusion’s Passenger came out and that was easy enough to get running. However, I was itching to try something new, improve the speed of my sites and lower the amount of resources that were being used on my Slice. Enter Nginx.
Here’s why I decided to give Nginx a shot:
- Nginx is lightweight and has a small memory footprint
- Nginx is super fast
- Nginx can be easily configured to send rails requests to mongrel, thin and others
- Nginx has easy to read configuration logs and rewriting rules
- I get to learn something new!
Note: All ApacheBench test results displayed are the from the 4th consecutive test. This minimizes the negative effects of the slow startup of ruby processes with Phusion Passenger where the initial requests take a considerably long time.
Apache vs. Nginx Memory Usage
For this test I ran ApacheBench against the index page of a well trafficked PunBB forum that I host on my slice. I fired up top and found the following:
Apache
Mem: 262316k total, 207140k used, 55176k free, 4280k buffers
Nginx
Mem: 262316k total, 146956k used, 115360k free, 3844k buffers
That’s about 40MB less with Nginx. That makes a big difference when you’re only starting out with 256MB.
Apache vs. Nginx AB results
Apache
This is ApacheBench, Version 2.0.41-dev <$Revision: 1.141 $> apache-2.0
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
Benchmarking www.example.com (be patient).....done
Server Software: Apache
Server Hostname: www.example.com
Server Port: 80
Document Path: /
Document Length: 8857 bytes
Concurrency Level: 10
Time taken for tests: 1.732965 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 928532 bytes
HTML transferred: 897838 bytes
Requests per second: 57.70 [#/sec] (mean)
Time per request: 173.296 [ms] (mean)
Time per request: 17.330 [ms] (mean, across all concurrent requests)
Transfer rate: 522.80 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 22 26 4.3 26 40
Processing: 70 136 41.5 133 268
Waiting: 46 105 40.9 100 239
Total: 93 163 42.4 160 294
Percentage of the requests served within a certain time (ms)
50% 160
66% 174
75% 186
80% 197
90% 213
95% 250
98% 274
99% 294
100% 294 (longest request)
Nginx
This is ApacheBench, Version 2.0.41-dev <$Revision: 1.141 $> apache-2.0
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
Benchmarking www.example.com (be patient).....done
Server Software: Nginx/0.6.32
Server Hostname: www.example.com
Server Port: 8080
Document Path: /
Document Length: 8858 bytes
Concurrency Level: 10
Time taken for tests: 1.107068 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 929232 bytes
HTML transferred: 897920 bytes
Requests per second: 90.33 [#/sec] (mean)
Time per request: 110.707 [ms] (mean)
Time per request: 11.071 [ms] (mean, across all concurrent requests)
Transfer rate: 819.28 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 22 25 4.3 25 42
Processing: 62 80 29.4 75 345
Waiting: 37 49 10.6 47 93
Total: 85 106 29.5 100 368
Percentage of the requests served within a certain time (ms)
50% 100
66% 105
75% 109
80% 112
90% 119
95% 146
98% 147
99% 368
100% 368 (longest request)
There are a few things that stand out to me from these tests:
- Requests Per Second: 90 vs 58, Nginx wins
- Mean Processing Time: 80 vs 136, Nginx wins
- Percentage of Requess served within 100ms: 50% vs. ??, Nginx Wins
Nginx and Thin vs. Apache and Phusion Passenger
So the PHP/MySQL stuff was all fine and good and that’s something that Apache and Nginx do very well, so no real surprises there. What about handling requests to a simple rails application like this blog?
For this test I again ran apache bench against the non-cached version of my root url. On this page there are some partials being rendered, active record database calls, images loading from Amazon’s S3 and some static files being served.
Apache 2.2 + Phusion Passenger 2.0.3
This is ApacheBench, Version 2.0.41-dev <$Revision: 1.141 $> apache-2.0
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
Benchmarking www.lengelzigich.com (be patient).....done
Server Software: Apache
Server Hostname: www.lengelzigich.com
Server Port: 80
Document Path: /
Document Length: 14894 bytes
Concurrency Level: 10
Time taken for tests: 26.118296 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 1544644 bytes
HTML transferred: 1493235 bytes
Requests per second: 3.83 [#/sec] (mean)
Time per request: 2611.830 [ms] (mean)
Time per request: 261.183 [ms] (mean, across all concurrent requests)
Transfer rate: 57.74 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 22 24 1.5 25 27
Processing: 769 2477 389.8 2524 3076
Waiting: 744 2448 387.8 2498 3048
Total: 792 2501 390.1 2547 3102
Percentage of the requests served within a certain time (ms)
50% 2547
66% 2637
75% 2793
80% 2819
90% 2906
95% 2963
98% 3079
99% 3102
100% 3102 (longest request)
Nginx + Thin
I decided to use thin instead of mongrel because, well, I guess I just wanted to try something new. I heard that thin had recently hit version 1.0 and figured it was worth checking out.
This is ApacheBench, Version 2.0.41-dev <$Revision: 1.141 $> apache-2.0
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
Benchmarking www.lengelzigich.com (be patient).....done
Server Software: Nginx/0.6.32
Server Hostname: www.lengelzigich.com
Server Port: 80
Document Path: /
Document Length: 14894 bytes
Concurrency Level: 10
Time taken for tests: 17.334487 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 1534900 bytes
HTML transferred: 1489400 bytes
Requests per second: 5.77 [#/sec] (mean)
Time per request: 1733.449 [ms] (mean)
Time per request: 173.345 [ms] (mean, across all concurrent requests)
Transfer rate: 86.42 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 22 24 1.4 25 26
Processing: 526 1663 489.6 1544 2995
Waiting: 477 1613 491.6 1496 2949
Total: 549 1687 489.9 1567 3020
Percentage of the requests served within a certain time (ms)
50% 1567
66% 1882
75% 1947
80% 2034
90% 2394
95% 2648
98% 3020
99% 3020
100% 3020 (longest request)
The results here are a little more impressive.
- Requests Per Second: 6 vs. 4, not great, but Nginx wins
- Mean Processing time: 1660 vs. 2448, Nginx wins
- Percentage of Requess served within 1560ms: 50% vs. ??, Nginx Wins
I don’t have the top memory output for these two tests handy, but with Apache free memory was hovering around 3MB. Nginx had free memory hovering around 12MB.
The key difference between Nginx and Apache is that with Apache there is a noticeable lag while Ruby processes are spun up by Passenger on the initial request, however, as I mentioned above, this is not reflected in these ApacheBench tests.
Plus, I Learned A Lot!
I think the best part of all of this was the overall learning experience. I broke out of my Apache shell and learned about a new web server, here are the highlights:
- Learned how to install and configure Nginx, php-cgi, spawn-fcgi and thin on Ubuntu
- Wrote new Capistrano deployment recipes to handle deploying to my new Nginx + thin setup
- Created some new shell scripts to mimic common tasks from apache2ctl and a2ensite/a2dissite
- Recreated my existing Apache virtual host setup with Nginx
If you’re currently running LAMP or using Apache and “mod rails”, give Nginx a shot. It’s easy to setup, doesn’t use too many resources, and best of all, it’s fast.












