This plugin is very similar to the built-in Rails ‘caches_page’ functionality, except it caches to memcached rather than a file. It relies on the ‘memcached_pass’ nginx directive to serve pages directly from memory if possible, and only passes to rails if necessary. On my server I’ve seen a 75% reduction in Ruby memory usage using this technique.
This approach is quite heavy-handed, and works best when the content you are serving changes rarely. If you have highly dynamic content, you’re probably better off developing your own, more finely-grained caching. It won’t work if the pages you are serving have some kind of user-specific info in the page (eg. the logged-in user name in the page header).
- Install a couple of memcache gems
- Copy memcaches_page.rb into the ‘lib’ directory of your rails app.
- Add the following to the bottom of your environment.rb :
1 2 3 4 5 6 7 8 9 10 11 12 13
A few things to note : Set the namespace to something appropriate for your app - you’ll need it later when you set up nginx. The MemcachedPageKeyPrefix should be set if you run your Rails app from a subfolder - leave blank otherwise. The MemcachedPageTtl is the time-to-live (in seconds) in the cache - I set it for a week which is fairly excessive - you probably only need a few hours, depending on what you’re trying to achieve. Point Cache.servers at the server/port you are running memcached on. * To cache every action in a controller, add the following filter to any controllers you want to cache :
Alternatively, add the following line near the top of your controller to cache specific actions only (where ‘view’ and ‘list’ are actions you want to cache :
When the page is rendered, the memcaches_page plugin will kick in, and save a copy of the page to your memcache. Rails never uses this cached version directly - in section (7), you’ll configure nginx to check the cache before passing requests to Apache. * Install phusion passenger
- Configure apache - For example, I run wordpress on my main domain (recurser.com), and a rails app (Redmine) in recurser.com/code/. Apache is configured with the following settings for the recurser.com domain :
1 2 3 4
For the complete config, see apache_example.conf * Configure nginx - for the complete config, see nginx_example.conf . The important sections for our purposes are : ** Set up a ‘backend’ service called ‘apache’ to pass requests to:
1 2 3
** Catch requests to the ‘/code’ subdirectory, and try to serve them from the cache:
1 2 3 4 5 6 7 8 9 10
This does a couple of things :
If the request is a POST, serve from Apache and ignore the cache
Set the memcached key to lookup, and serve the page directly from memcached if possible (memcached_pass directive).
* If the page is not in the cache, pass the request back to the ‘backend’. Make sure the code.recurser.com part of the key matches what you set as the :namespace in step (3)! Set up the ‘backend’ proxy that passes to apache:
1 2 3