Capistrano, Mongrel, and Mongrel_cluster

EDIT 2007-06-05: An updated version of this is up here

After my hiatus on posting it seems appropriate to get back into the meaty stuff…

Ever since I started using Debian (instead of FreeBSD) I’ve been having weird problems with my rails dispatch.fcgi processes multiplying in the night. Nothing shows up in the logs, but I spawn 2 externally of Lighttpd, and in the morning i’ve got 6 of the little blighters. Of course, at 20-30 meg a pop, the poor little Xen VPS isn’t too happy about that, so I have a nightly job that kills them all and restarts them. And then, 12 hours later, 4 more than I asked for are there. It seems to be a load issue, but I digress.

So ever since I noticed that I’ve been wanting to use Mongrel to run my Rails apps. For those not familiar with mongrel, it’s a Tomcat-style application host for rails apps that avoids (huzzah) the FCGI palaver that we ordinarily have to deal with. The problem was that according to mongrel, a USR2 signal should fully restart the daemon, and it does, but it’s a tiny little bit funny in a way that makes it totally painful to use with Capistrano for automated deployment.

You see, on restart, it doesn’t re-evaluate what the ./current symlink is pointing to. So when it’s restarted over a ./current that points to ./releases/2006xxxxxxxxx1 that’s fine, but on a redeployment through Cap when this symlink is repointed to ./releases/2006xxxxxxxxx2, the mongrel instance still points to ./releases/2006xxxxxxxxx1

So that’s not so good. Btw, Zed, you’re an awesome coder and I in no way mean you disrespect here. I’m just telling the problem I faced.

Along comes mongrel_cluster. Totally fixed the issue for me, and here’s how.

1. Install mongrel_cluster, and then (in ./current) run “mongrel_rails cluster::configure”

2. open the new ./config/mongrel_cluster.yml and edit the line that starts with “cwd:” like so:

  • change “cwd: /path/to/app/releases/2006xxxxxxxxx1” to “cwd: /path/to/app/current”
  • change the port to the first one you want for this cluster, and select how many you want (defauts to 2 which should be ‘enough’ for most cases)
  • change from “development” to “production”

3. Add the following tasks to your capistrano deploy.rb file

desc “The spinner task is used by :cold_deploy to start the application up”
task :spinner, :roles => :app do
send(run_method, “cd #{deploy_to}/#{current_dir} && mongrel_rails cluster::start”)
end

desc “Restart the mongrel cluster”
task :restart, :roles => :app do
send(run_method, “cd #{deploy_to}/#{current_dir} && mongrel_rails cluster::restart”)
end

4. Rejoice!

5. Before you do anything else, add to your crontab an @restart task to start the mongrel instances when your server comes up! Very important!

Now “rake remote:cold_deploy” and “rake remote:deploy” work for the mongrel cluster! I used the instructions on the mongrel site on how to integrate with lighttpd at http://mongrel.rubyforge.org/docs/lighttpd.html but there are equally good Apache 2.2 docs out there (why Apache 2.2 isn’t available for Debian is anoher question entirely…)
Much kudos and thanks to Zed Shaw for the excellent mongrel server and to Bradley Taylor for mongrel_cluster. Oh, and Jamis Buck for Capistrano!

13 Responses to “Capistrano, Mongrel, and Mongrel_cluster”

  1. Thom May says:

    Apache 2.2 isn’t available in Debian yet for a number of reasons, mostly related to the lack of time available to the packagers :-) The major stoppers are the need for porting of both authentication modules and major apps such as mod_python (because we’d replace 2.0 with 2.2, rather than going through another nightmare of multiple apache versions), and some config clean-up.
    That said, expect it to hit experimental reasonably soon.

  2. Jay P. says:

    Fantastic guide, Dan! Isn’t it strange how just when you’re thinking of using something neat (as I was with Ruby Servlet clustering), you trip on it on someone else’s blog? :)

    As I was reading this, the second I saw that you actually used the word “palaver” in a sentence, I threw this on my Del.icio.us feed. I love seeing Polari make its way into literature. :)

    By the way, I noticed you’re using WordPress for your blog. I’ve lately been working a Rails app called Gosling which serves content from a WordPress legacy database. Perhaps this is something you’d be interested in playing with? My site Jicksta.com is a live demo of it.

    Jay

  3. Jim Morris says:

    Hi, nice thanks…

    One comment though :)

    won’t ./config/mongrel_cluster.yml get wiped out every time you do a deploy? unless it is checked into svn?

  4. dansketcher says:

    Yep, you’re dead right Jim… I’ve checked it in. Thanks for the pickup :)

  5. WIll says:

    Thank you. Very useful.

    One thing: if your tasks are going to include ‘cd’ commands then you have to make sure that capistrano isn’t going to use ‘sudo’ to run them, as cd is a shell builtin and can’t be sudoed. I think 1.2 sudoes by default, but you can edit gems/capistrano-1.2.0/lib/capistrano/recipes/standard.rb to change that behaviour.

  6. if you just put a “;” in front of th “cd” like this :

    send(run_method, “;cd #{deploy_to} ….

    you won’t have to hack capistrano/recipes/standard.rb

    cap will just return the sudo usage

    Thanks for your tutorial !

  7. Balaji says:

    putting a ; in front of the CD wont help. Something like the following will help:

    send(run_method, %{sh -c “cd #{current_path} && mongrel_rails cluster::restart”})

  8. belpoub says:

    easyest way to avoid sudo is with the run CMD:

    desc :app do
    run

  9. belpoub says:

    Sorry, I passed code in here and it was truncated,
    please let me know how I ca do so.
    let’s try again, remove the # in front of each line.
    #desc :app do
    #run

  10. belpoub says:

    well still not good, just use the run CDM command with this:
    cd #{deploy_to}/#{current_dir} && mongrel_rails cluster::start

  11. Brian McQuay says:

    Nice work. Thanks for the tips.

  12. abdou says:

    intresting blog