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 PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin set -e # Parse command line parameters. case $1 in start) echo -n "Starting Solr: " su - paul -c "cd /web/company/solr && nohup /usr/bin/java -DSTOP.PORT=8079 -DSTOP.KEY=ftasolrstop -Dsolr.data.dir=solr/data/production -Djetty.port=8983 -jar start.jar > logs/solr.log 2> logs/solr.err.log &" echo "ok" ;; stop) echo -n "Stopping Solr: " cd /web/company/solr /usr/bin/java -DSTOP.PORT=8079 -DSTOP.KEY=ftasolrstop -jar start.jar --stop echo "ok" ;; restart) 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 -Dsolr.data.dir=solr/data/production -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 ;; esac exit 0
I hope this helps someone!