Liquid Media's Apps

Hints for deploying Solr for Rails projects

I had a lot of trouble today getting acts_as_solr deployed. In the end, I hit upon the following keys:

1: Life is easier if you separate Solr from your Rails app
As a rule, I want my development environment to resemble my deployment environment. That would mean that I would run Solr from the vendor/plugins/acts_as_solr directory with the usual RAILS_ENV=production rake solr:start. This means that with every Capistrano deploy, you need to shut down and restart the Solr service. This has a few problems:

  • Why restart a service that doesn't need to be restarted and only slows down your deploy?
  • When I expand to multiple app servers, I don't want to shut down and restart Solr servers as well.
  • If I start Solr with a Capistrano deploy, how do I start Solr if my computer reboots?

Ultimately I decided that I'm better off if I decouple Solr from Rails. By decoupling, I can put Solr in its own directory and start/stop Solr on its own, usually timed with system startup and shutdown. It also becomes easier to monitor Solr separately with tools such as Monit and God.

My approach to decoupling was simple. Assume my project is located in /web/company/project, I copied /web/company/project/vendor/plugins/acts_as_solr/solr to /web/company. Yes, this isn't very DRY, but oh well. I suppose to solve the DRYness problem, I can delete the vendor/plugins/acts_as_solr/solr directory entirely, but then I won't be able to start Solr on my development machine.

2: Starting Solr in init.d is surprisingly challenging
It took me a while to find out how to start Solr. By default, Solr doesn't daemonize. Once you get Solr to daemonize, it's hard to determine it's PID.

For the first problem, the solution to wrap your Solr startup in nohup and &. The second problem is resolved by using a feature of Java (or is it Solr?) command line option I didn't know about: --stop which depends on -DSTOP.KEY and -DSTOP.PORT. Apparently to shut down a daemonized Java app you send it a stop signal over a TCP port. (If anyone wants to clarify, please jump in — I'm guessing at the details here.) My final /etc/rc.d/init.d/solr script is as follows:

#! /bin/sh

# chkconfig: 2345 98 02
# description: Solr starter

# Place this file at /etc/init.d/solr (or
# /etc/rc.d/init.d/solr) and make symlinks to
#   /etc/rc.d/rc0.d/K02solr
#   /etc/rc.d/rc1.d/K02solr
#   /etc/rc.d/rc2.d/K02solr
#   /etc/rc.d/rc3.d/S98solr
#   /etc/rc.d/rc4.d/S98solr
#   /etc/rc.d/rc5.d/S98solr
# Or, if you have chkconfig, simply:
# chkconfig --add solr
# The path that is to be used for the script

set -e

# Parse command line parameters.
case $1 in
        echo -n "Starting Solr: "
        su - paul -c "cd /web/company/solr && nohup /usr/bin/java -DSTOP.PORT=8079 -DSTOP.KEY=ftasolrstop -Djetty.port=8983 -jar start.jar > logs/solr.log 2> logs/solr.err.log &"
        echo "ok"
        echo -n "Stopping Solr: "
        cd /web/company/solr
        /usr/bin/java -DSTOP.PORT=8079 -DSTOP.KEY=ftasolrstop -jar start.jar --stop
        echo "ok"
        echo -n "Restarting Solr: "
        cd /web/company/solr
        /usr/bin/java -DSTOP.PORT=8079 -DSTOP.KEY=ftasolrstop -jar start.jar --stop
        su - paul -c "cd /web/company/solr && nohup /usr/bin/java -DSTOP.PORT=8079 -DSTOP.KEY=ftasolrstop -Djetty.port=8983 -jar start.jar > logs/solr.log 2> logs/solr.err.log &"
        echo "ok"
        # Print help
        echo "Usage: $0 {start|stop|restart}" 1>&2
        exit 1

exit 0

I hope this helps someone!

Tagged acts_as_solr, apache, init.d, java, rails, and solr.
blog comments powered by Disqus