There’s a surprisingly small amount of documentation out there on tuning Apache for optimum Rails performance. Almost everyone mentions the first step (use FastCGI, not regular CGI), but that’s such a huge performance boost that it’s really obvious–waiting 2-3 seconds per hit for Rails to start up is an indicator that you’re doing something wrong.
Once you get past that, there’s not a lot of documentation. There are examples from place to place, but no one seems to discuss what they mean or why they should be used.
Ever since I switched to Typo, I’ve been seeing occasional HTTP 500 errors from Apache, suggesting that Apache was unable to talk to Typo. Looking in the logs shows that Apache was usually in the middle of restarting a FastCGI instance whenever the errors occurred. Digging through the mod_fastcgi shows that FastCGI can work in three different modes with Apache:
- Static. FastCGI servers are started when Apache is reloaded and remain running.
- Dynamic. FastCGI server processes are started whenever a FastCGI URL is hit. Excess processes are killed off when there’s no traffic.
- External. Apache and your FastCGI app talk via TCP sockets.
Dynamic mode is the default, but that’s not a good fit for Rails, because of its slow startup time. Switching to static mode really helps. To do that, I added this line to
/etc/apache2/apache.conf on my Debian server:
FastCgiServer /var/web/typo/public/dispatch.fcgi -idle-timeout 120 \ -initial-env RAILS_ENV=production -processes 2
Notice that I had to list the full path to Rails’s
dispatch.fcgi file; on some systems you may be able to get away with only listing
public/dispatch.fcgi, but that will almost certainly not work if you’re using virtual hosting.
By default, FastCGI assumes that your server will respond to queries within 30 seconds. I added the
-idle-timeout 120 parameter just so I can deal with really slow responses better. Typo’s article admin page currently tries to list all 466 articles on one page, and that can take over 30 seconds to process.
-processes parameter tells Apache how many FastCGI processes should run for this application. For 95% of users, 1 or 2 will be best. If you get a lot of traffic, then raising this to 3-4x the number of CPUs in your system might get you slightly better performance.
-initial-env bit makes sure that Rails runs in production mode, talking to my production DB and not returning error backtraces to the user.