Lightweight, fast Rails stack - Thin & nginx

Since purchasing a slice of heaven a few days ago, I’ve setup a very lightweight Rails stack consisting of Thin & nginx for my Rails needs. Since I went for a slice with just 256MB of RAM, memory consumption becomes a pretty serious issue. nginx has been around for quite a while now, and has recently started to become more and more popular in Rails deployments due to the fact that’s incredibly lightweight, very fast and stable – perfect not only for VPS jerks like me, but for anyone who really doesn’t feel it’s necessary to run Apache for static content/cluster proxying/load balancing. Thin is something I came across very recently and I decided to try is as a replacement for mongrel since I’d heard some great things about it, even if it is still alpha. It’s performance in comparison to mongrel (even with a tacked on event machine) looks very impressive on paper.

Setting up clustering with it is a snap, just spawn the processes and pipe them into nginx. Here’s a startup script borrowed from Stephen Celis:

namespace :thin do
namespace :cluster do desc ‘Start thin cluster’
task :start => :environment do
`cd #{RAILS_ROOT}`
port_range = RAILS_ENV == ‘development’ ? 3 : 8
(ENV[‘SIZE’] ? ENV[‘SIZE’].to_i : 4).times do |i|
Thread.new do
port = ENV[‘PORT’] ? ENV[‘PORT’].to_i + i : (“#{port_range}%03d” % i)
str = “thin start d -p#{port} -Ptmp/pids/thin#{port}.pid”
str = " e#{RAILS_ENV}"
puts str
puts “Starting server on port #{port}…”
`#{str}`
end
end
end
desc ‘Stop all thin clusters’
task :stop => :environment do
`cd #{RAILS_ROOT}`
Dir.new(“#{RAILS_ROOT}/tmp/pids”).each do |file|
Thread.new do
if file.starts_with?("thin
")
str = “thin stop -Ptmp/pids/#{file}”
puts "Stopping server on port #{file[/\d
/]}…"
`#{str}`
end
end
end
end
end
end

Then spawn however many processes you want using something like:
rake thin:cluster:start RAILS_ENV=production SIZE=2 PORT=3000

To stop them, use:
rake thin:cluster:stop

With that all nicely setup, you can use an nginx config similar to mine to get things in order:
upstream dapperjerk {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
}

server {
listen 80;
server_name www.dapperjerk.com;
rewrite ^/(.*) http://dapperjerk.com permanent;
}

server {
listen 80;
server_name dapperjerk.com;

access_log /home/jason/public_html/blog/log/access.log; error_log /home/jason/public_html/blog/log/error.log; root /home/jason/public_html/blog/public/; index index.html; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect false; if (-f $request_filename/index.html) { rewrite (.*) $1/index.html break; } if (-f $request_filename.html) { rewrite (.*) $1.html break; } if (!-f $request_filename) { proxy_pass http://dapperjerk; break; } }

}


And that’s really all there is too it. I’m not a masochist so I’ve never bothered to fully read Apache’s documentation, but I don’t think I’m going out on a limb here by saying that it seems to be a lot easier to manage nginx. I haven’t really put thin through its paces yet, but we’ll see in the coming weeks as I cobble together a custom blog app to run this place.


  1. roger says:

    Note that thin is faster, but that the difference isn't extreme[1].

    [1] http://oldmoe.blogspot.com/2008/01/numbers-are-in-thin-is-sort-of-faster.html

Post a comment


(lesstile enabled - surround code blocks with ---)