Just what web server should be sitting in front of my Rails application?

The one you feel comfortable configuring, maintaining and perhaps extending.

That one.

As web server/reverse proxy schizoserverphrenia tends to sweep through the Rails community from time to time, I see questions of which is “best” so I thought I’d add some numbers here.

These are from April-ish 2006, and were in various places on weblog.textdrive.com and joyeur.

So with

  1. A “Hello World” controller
  2. A good deal of tuning (for example, a fat untuned Apache was 4x slower then my quickly tuned one -> 250ish versus 1000ish)
  3. Comparing similar numbers for FreeBSD and Solaris for various combinations of client, proxy server and rails application servers on absolutely equivalent hardware and all gigabit networking
  4. Using ab, httperf, siege and tsunami and multiple datasets.
  5. Your realization that this is looking at reverse proxy performance only
  6. Knowledge of Apache tuning since it was 0.6
  7. With being around just about every web server, forward proxy cache, reverse proxy cache and load balancer that has been created and either made public, sold or passed among friends.
  8. And having advocated lighttpd use in Rails a “long” time ago as we were getting away from Apache-mod_ruby, and Mark has blabbered about it all as well.

Some representative numbers with FreeBSD client -> FreeBSD web/proxy -> Solaris Rails application server

Litespeed Enterprise 2.1.14 -> Mongrel
Concurrency Level: 100
Requests per second: 1008.04 [#/sec] (mean)

Lighttpd 1.4.10 -> Mongrel
Concurrency Level: 100
Requests per second: 1010.36 [#/sec] (mean)

I was a fan of apache 1.3’s mod_accel which was by the nginx dude, so 0.3.37 made it in

nginx 0.3.37 -> Mongrel
Concurrency Level: 100
Requests per second: 1016.40 [#/sec] (mean)

Zeus -> Mongrel
Concurrency Level: 100
Requests per second: 25.07 [#/sec] (mean)

(Zeus still did 1300+ req/sec on static files with the same configuration).

Apache 2.2 worker (with mod proxy balancer) -> Mongrel
Concurrency Level: 100
Complete requests: 10000
Requests per second: 1452.23 [#/sec] (mean)

Apache 2.0 using the prefork MPM, only mod_proxy
Concurrency Level: 100
Complete requests: 10000
Requests per second: 1070.59 [#/sec] (mean)

What’s the lesson I learned from this?

That when you spend a while tuning each, digging through their code and instrumenting, there is not a significant difference between these when it comes their ability to be a reverse proxy server in terms of throughput. There is a significant difference in what one does “out of the box” and there are more significant differences in their abilities to serve static files and in their memory footprints.

And there was one thing that became very clear though through all of them and that was differences in their horizontal scalability. Covered here

What do I like as the current?

Dynamic Rails Parts

F5 BIG-IPs -> Varnish -> F5 BIG-IPs -> Mongrel

Varnish by the way is a fine piece of software mainly written by the incredible PHK and with the VCL’ed PURGE function in which you can programmatically clear things from the cache (ticket). Did you hear what I said? You can have this very fast cache do all the caching for your Rails applications (or anything for that matter), and when something is updated in your application, you can actually have it ping the cache with a

"PURGE /images/207/123/52db760df37da63a1c9d94a1be6fcf6f.jpg HTTP/1.0"


Mongrel has been good, but right now JRuby-Glassfish is doing a bit of a siren’s song because of some places it can help in the backend (and it also happens to be fast).

Static Non-Rails Parts

Level3 CDN -> F5 BIG-IPs -> Varnish -> Nginx

A CDN is a good thing, the F5’s are there because they’re faster than Varnish, and Varnish is faster than nginx (and also not a web server).

7 responses to “Just what web server should be sitting in front of my Rails application?”

  1. Why are you testing ancient versions of both mongrel and nginx? Mongrel is at 1.0.1 now and has made a lot improvements since 0.3.12. And nginx is at 0.6.x. and has improved vastly since 0.3.37. Any reason to use such ancient versions in these benchmarks?

  2. As Jason mentioned, this is a sum up from tests he performed in April 2006.

  3. Any statistics of using Pound in front of a Mongrel cluster?

  4. So using varnish allows you to do caching with a BigIP without having the mongrels be involved in serving the cached files?

    A mongrel can serve about 600-700 static files per second I’ve found. It’s fast enough for me. Considering I have 30 of them running. 😀

  5. @ Ezra

    It’s about a truly comparative dataset and putting actual numbers on things, and yes I know mongrel is at 1.0.1 and nginx is at 0.6, and while they are better, I wouldn’t call the performance “vastly” improved. Meaning they aren’t a log better right?

  6. What about for a very low traffic intranet app? Would Varnish be appropriate to cache and speed up the slow requests, or would you consider it too heavy-handed for such a light usage scenario?

    If it would be useful, how would the architecture change?

    Varnish -> NGINX -> Mongrel ?

    If I’m understanding correctly, Varnish runs on 80, if a cache misses, it reverse proxies back to NGINX. If the request was static, NGINX serves it up, if the request was dynamic, NGINX passes it back to Mongrel? Is that even close?

  7. Jason,

    Do you have a good/basic varnish config file that you can share? I think I have the basics working but it’s throwing hate on anything that has a session. Goal would be to cache some partials.

    Here’s what I have so far.