Posts Tagged ‘mongrel’

Force mongrel to delete stale pid files upon launch

Monday, February 4th, 2008

Mongrel, currently the mainstream Rails server, has a nasty habit of not deleting its PID files when it crashes and burns. This then occasionally stops automatic restarts because mongrel sees its old PID files, assumes it’s running (without a check) and refuses to start.

All that needs to be done is a startup check that the process mentioned in the PID file is actually running. This has been implemented in a patch here which I’ve integrated and successfully tested. If you’d like to use the file I generated, I’ve attached it below. Simply replace /path/to/gems/mongrel-1.1.3/bin/mongrel_rails with the attached file and run as normal. You’ll want to make a backup copy first, of course!

Also on the “things to do while hacking mongrel” list is to change the fucking version so it’s actually up to date as echoed in your console log. The file is lib/mongrel/const.rb line 68,

MONGREL_VERSION="1.1.3".freeze

which the maintainers obviously missed.

Mongrel is an aptly named bit of software, poorly maintained and with many long-standing patches which should have been included long ago. This particular patch fixes an annoying bug which shouldn’t exist any more – and harks back to March 2007, 10 months ago. That’s a pretty unforgivably long time not to include something as basic as this. And as far as I can tell the mongrel_rails program hasn’t changed significantly since last time – there’s no excuse for this, and other, patches to have not made it in by now. This is the third time I’ve manually patched it like this, and was only reminded to do so in the latest version (1.1.3) when I noticed – surprise! – it was again refusing to start with a stale PID.

I’d be more worried if there weren’t several promising alternative servers on the rise. Hopefully the Rails community’s dalliance with the very doglike mongrel won’t last too much longer…

mongrel_rails – full file

mongrel_stale_pid_file.patch – same thing in patch form. Run

$ cd /path/to/gems/mongrel-1.1.3/
$ patch -p0 < /path/to/mongrel_stale_pid_file.patch

Both from http://textsnippets.com/posts/show/931.

Testing (on MacOSX):

$ cd ~/Desktop
$ /usr/bin/ruby /usr/bin/mongrel_rails start -d -e development -p 3000 -a 127.0.0.1 -P /Users/sho/Desktop/mongrel.pid -c /rails/myapp
# mongrel starts ...
$ cp mongrel.pid another.pid
$ /usr/bin/ruby /usr/bin/mongrel_rails stop -P /Users/sho/Desktop/mongrel.pid
Sending TERM to Mongrel at PID 1605...Done.
$ cp another.pid mongrel.pid
$ /usr/bin/ruby /usr/bin/mongrel_rails start -d -e development -p 3000 -a 127.0.0.1 -P /Users/sho/Desktop/mongrel.pid -c /rails/myapp
** !!! PID file /Users/sho/Desktop/mongrel.pid exists, but is stale, and will be deleted so that this mongrel can run.
# mongrel starts as hoped .. success!

Zed Shaw goes postal

Wednesday, January 2nd, 2008

Zed Shaw, the writer of the popular essential server software mongrel, goes absolutely fucking nutzoid insane on his weblog in a 6000-word essay on what he hates about, well, pretty much everything to do with Rails.

Jesus H Christ, he really gets into it. Now I’m a big fan of dissing DHH and everything, but man, Zed just takes it to a whole new level of bitterness. And there’s some pretty scary disclosures, like when DHH admits to Shaw on IRC that he couldn’t keep 37Signal’s flagship products up for more than 4 minutes at a time:

(15:11:12) DHH: before fastthread we had ~400 restarts/day
(15:11:22) DHH: now we have perhaps 10
(15:11:29) Zed S.: oh nice
(15:11:33) Zed S.: and that’s still fastcgi right?

Recommended reading, it’s a laugh riot. Couldn’t agree with him more on most of it re. the idiots in the community.

Rails: multiple assets servers with 1 server using Apache

Wednesday, December 5th, 2007

Rails 2 has added the ability to automatically serve static public files – “assets” – from multiple servers, to speed up loading times. This is well worth implementing and will speed loading times considerably. And it’s very simple to do. You’ll need Rails 2.0RC1+ for this. Obviously your implementation details may differ, especially filepaths on the server.

Step 1: In rails_app/config/environments/production.rb:

config.action_controller.asset_host = "http://assets%d.my_kewl_domain.com"

Step 2: In my_kewl_domain.com.zone

www              IN              A       31.337.31.337
 
assets0         IN              A       31.337.31.337
assets1         IN              A       31.337.31.337
assets2         IN              A       31.337.31.337
assets3         IN              A       31.337.31.337

Step 3: In httpd.conf

<VirtualHost 31.337.31.337:80>
ServerName assets0.my_kewl_domain.com
ServerAlias assets1.my_kewl_domain.com, assets2.my_kewl_domain.com, assets3.my_kewl_domain.com
DocumentRoot /www/my_kewl_domain.com/current/trunk/public
VirtualHost>

Note this is a separate vHost from your main application. Note also that it is looking straight into the /public directory of your app.

svn up, cap deploy, restart %w[named httpd mongrel] and you’re done.

Including the coming Ruby 1.9 (apparently still on course for sometime this month), this is a nice free speedup for your application.

Hosting Rails is a bitch

Friday, October 5th, 2007

No matter what anyone says, hosting Rails applications is – and is likely to remain for the foreseeable future – a cast-iron bitch. An expensive, slow one, too.

I’m no stranger to web hosting. I set up my first web server over 10 years ago – manually, of course, none of these control panels, and have done it many times since, as technology changed and languages shifted. I’ve been responsible for the production web presence of a number of companies, and along the way I’ve dabbled with a number of server-side application technologies, including ColdFusion and even Java (ugh!) but mostly PHP, since that’s what everyone uses.

And for good reason. PHP has many flaws as a language, mainly to do with security and the hideous mess most projects in PHP comprise, but it’s a joy to deploy. Here’s how it works.

PHP is actually two things. It’s a language, and a compiled executable which will interpret and act on commands issued in that language. It integrates nicely with the most popular, and largely considered best, front-end web server software, apache, so that what happens when a PHP web page is requested is as such:

  1. Apache reads the web page, typically page.php, and determines it requires action by the PHP interpretor, and creates an instance of that
  2. The commands in the page are relayed to the PHP interpretor instance
  3. The interpreter processes the commands and performs whatever action is required, typically HTML generation and/or database actions
  4. Apache receives back the data and serves it inline with the rest of the web page.

This all happens extremely quickly, and since PHP is integrated so tightly with Apache, you only have to worry about maintaining that one application. Sure, you configure PHP – via a single .ini file. Everything else is Apache all the way, and it’s a highly reliable and very fast way to serve web pages.

An especially welcome benefit from this arrangement is that you only require one Apache server running to serve any number of PHP applications. You can easily configure Apache to serve any number of domains via its VHosts system, any or all of which may contain active PHP pages. Apache simply instantiates (and destroys) PHP instances, which respond to the relevant pages, whenever required. The PHP executable doing the interpreting neither knows nor cares where the commands it’s interpreting come from. You’ve effectively created a “pool” of servers, any of which can respond to any PHP application, and Apache can balance its load amongst them as required.

The situation with a Rails application is very different, and not in a good way.

The current “best practise” for deploying a single Rails application is as follows:

1. Apache server front end, with a vhost interpreting the URL and relaying relevant requests to a cluster of mongrel servers, addressable by (local) IP
2. User then configures and maintains a seperate cluster of mongrel servers dedicated to that single Rails application and responding on configured IPs as set in Apache
3. Apache is further configured to go through mongrel for every non-static request.

This is then repeated for every Rails application on the box.

This has several disadvantages compared to the situation with PHP, to wit:

  1. Administrator becomes responsible for setting up, maintaining, and constantly monitoring a collection of independently-running applications, in addition to the core Apache server
  2. Mongrel servers not currently being used are not destroyed, but continue running, wasting memory (every instance of mongrel currently running on my server uses in excess of 100M each)
  3. Members in a cluster must be predefined and cannot be allocated on the fly according to need. For example, If you have 1GB of memory and 3 Rails apps, you are limited to distributing about 10 instances of mongrel between them. You must decide this in advance. If one of the applications suddenly receives a lot of hits, performance will suffer while the other mongrels, for the other apps, sit unused – the opposite of the “pool” you have access to in a PHP situation

And this is before even mentioning the underlying speed of mongrel, Ruby and Rails in general, which can only be described as horrible.

So, the sequence of events when a page request for your Rails app comes in is as follows:

  1. Apache receives request, determine the request is for your rails app
  2. Apache picks a server in your mongrel cluster, and sends the request (NOT commands, as in PHP) to it
  3. Mongrel, moving with the lightning speed of a slug through treacle, goes through the request page and sends the relevant parts to the ruby interpreter, itself not much of a speed demon, which, after a lengthy time out for self-reflection and “me time” reluctantly listens to, thinks about, thinks about some more, and then finally responds to the command. Repeat for every ruby command on the page
  4. The mongrel cluster receives and compiles the completed requests and, taking its sweet time, eventually manages to respond with the complete page
  5. Apache passes on the completed page to the client.

Not many more steps there, I admit. But it’s the speed of it which is the killer. PHP commands are detected, seperated from enclosing HTML and dispatched from within Apache, a lightning-fast and time-proven, highly reliable web server written in C. But in Rails, the job of going through the page to find Ruby requests and dispatch them is performed by Mongrel – itself written in Ruby. I don’t have any figures depicting how much slower it is, but it is – a lot.

Combine that with the inflexibility of distributing resources where needed, and having to independently spawn and monitor a seperate cluster of servers for every seperate application and you’ll understand that when people say hosting Rails is a nightmare, they’re right.

Rails has a lot of things going for it. It’s a joy to write in, mostly, and the development environment is great. It’s much, much more productive than the likes of Java while being much, much nicer than PHP.

But it’s slow as hell, and deployment sucks, and don’t let anyone tell you otherwise.