Managing Multiple Mongrel Processes with mongrel_cluster

Problem

Your Rails application is being served by multiple Mongrel processes behind a load balancing reverse proxy. Currently, you are starting and stopping these individual process manually. You want an easier and more reliable way to deploy your application and manage these Mongrel processes.

Solution

Use mongrel_cluster to simplify the deployment of your Rails application using a cluster of Mongrel servers. Install the mongrel_cluster gem (and perhaps its prerequisite, Mongrel) with:

$ sudo gem install mongrel_cluster
Attempting local installation of 'mongrel_cluster'
Local gem file not found: mongrel_cluster*.gem Attempting remote installation of 'mongrel_cluster'
Install required dependency mongrel? [Yn] 
Select which gem to install for your platform (i486-linux)
 1. mongrel 0.3.13.2 (mswin32)
 2. mongrel 0.3.13.2 (ruby)
 3. mongrel 0.3.13.1 (mswin32)
 4. mongrel 0.3.13.1 (ruby)
 5. mongrel 0.3.13 (mswin32)
 6. mongrel 0.3.13 (ruby)
 7. Cancel installation
> 2
Building native extensions. This could take a while...
ruby extconf.rb install mongrel_cluster checking for main() in -lc... yes creating Makefile
...

mongrel_cluster adds a few more options to the mongrel_rails command. One of these options, cluster::configure, helps set up a configuration file that defines how each of your Mongrel process is to be started, including the user that the process runs as. It's a good idea to have a dedicated mongrel user and group for running these processes. Create a mongrel system user and group with your distribution's adduser and addgroup commands. (See the adduser manpage for the option required for creating system users.)

$ sudo adduser --system mongrel

The next step is to make sure this user has write access to your application, or minimally, the directory. Assuming your blog application is in , grant ownership on the entire application to the user mongrel (in the group www-data) with:

$ sudo chown -R mongrel:www-data /var/www/blog

Now use mongrel_rails's cluster::configure option to define the specifics of how each process is to be run. Make sure to run this command from your project root.

$ sudo mongrel_rails cluster::configure -e production \
> -p 4000 -N 4 -c /var/www/blog -a 127.0.0.1 \
> --user mongrel --group www-data

The -e option specifies the environment under Rails should be run. The options -p 4000 and -N 4 tell mongrel_cluster to create four process running on successive port numbers, starting with port 4000. The -c option specifies the path to the application you want this configuration applied to. The option -a 127.0.0.1 binds each process to the local host IP address. Finally, the mongrel user is specified as the owner of each process as a member of the www group. Running this command creates the following YAML file in your application's directory:

config/mongrel_cluster.yml:

--- 
user: mongrel cwd: /var/www/blog port: "4000"
environment: production group: mongrel address: 127.0.0.1
pid_file: log/mongrel.pid servers: 4

With this configuration in place, you can start the cluster by issuing the following command from your application's root:

$ sudo mongrel_rails cluster::start

To stop the cluster (i.e., kill the processes), use:

$ sudo mongrel_rails cluster::stop

You can view additional cluster options added to the mongrel_rails command by issuing it with no options:

$ mongrel_rails
** You have sendfile installed, will use that to serve files.
Usage: mongrel_rails <command> [options]
Available commands are:
 - cluster::configure
 - cluster::restart
 - cluster::start
 - cluster::stop
 - restart
 - start
 - status
 - stop Each command takes -h as an option to get help.

Discussion

Once you have your cluster up and running, you'll have four processes listening on ports 4000, 4001, 4002, and 4003. These process are all bound to the local host address (127.0.0.1). The next step is to configure your load balancing reverse proxy solution to point to these processes.

Once your system is up and running, you can experiment to find out how many Mongrel processes give you the best performance, based on system resources and the load you expect for our application.

On a production system, you'll almost certainly want to set your mongrel_cluster to be restarted on system reboots. mongrel_cluster has a few scripts that make it easy to set up automatic restarts, although the details of doing so depend on the *nix variant of your server. On a Debian GNU/Linux system, you start by creating a directory in where your system looks for the configuration of the service you're about to create. Within this directory, create a symbolic link to your application's mongrel_cluster configuration:

$ sudo mkdir /etc/mongrel_cluster

$ sudo ln -s /var/www/blog/config/mongrel_cluster.yml \
 /etc/mongrel_cluster/blog.yml

Now, copy the mongrel_cluster control script, from the directory of mongrel_cluster gem installation location, into .

$ sudo cp /usr/lib/ruby/gems/1.8/gems/\
>mongrel_cluster-0.2.0/resources/mongrel_cluster 

Finally, make sure the mongrel_cluster script in init.d is executable, and use update-rc.d to add Mongrel to the appropriate runlevels. (You should see output as evidence of this service being registered for each system runlevel.)

$ sudo chmod +x /etc/init.d/mongrel_cluster

$ sudo update-rc.d mongrel_cluster defaults
 Adding system startup for /etc/init.d/mongrel_cluster ...
 /etc/rc0.d/K20mongrel_cluster -> ../init.d/mongrel_cluster
 /etc/rc1.d/K20mongrel_cluster -> ../init.d/mongrel_cluster
 /etc/rc6.d/K20mongrel_cluster -> ../init.d/mongrel_cluster
 /etc/rc2.d/S20mongrel_cluster -> ../init.d/mongrel_cluster
 /etc/rc3.d/S20mongrel_cluster -> ../init.d/mongrel_cluster
 /etc/rc4.d/S20mongrel_cluster -> ../init.d/mongrel_cluster
 /etc/rc5.d/S20mongrel_cluster -> ../init.d/mongrel_cluster

See Also