• Skip to primary navigation
  • Skip to main content

Inodes

Fractional CTO Consulting

  • Home
  • About Us
  • Contact Us
  • Block Examples
  • Landing Page
  • Pricing Page
  • Show Search
Hide Search

Squid and Rails caching

John Ferlito · 15 January 2008 · 4 Comments

At Vquence our Rails setup looks something like this.

Plaintext
------------     ---------     ------------ 
| Internet |---->| Squid |---->| Mongrels | 
------------     ---------     ------------ 

(Who needs Inkscape when you have ASCII art)

This infrastructure is hosted in the US and up until recently squid hadn’t been doing much of anything except really sitting there.

Now a few months ago when we signed a contract with an Australian customer we decided we needed to place a squid cache in Australia which would actually cache content. For two reasons, firstly the US is a long way away and the 300ms latency is really noticeable and secondly because some of our pages involving graphs have long statistical calculations which can take minutes to render. (OK its really because no one has had a chance to optimise them yet but lets pretend that’s not the case). So we changed the above setup for the Australian customers to look like the following.

Plaintext
------------     ------------     ------------     ------------
| Internet |---->| Squid AU |---->| Squid US |---->| Mongrels |
------------     ------------     ------------     ------------

We hand out urls like http://www.client.b2b.vquence.com/widget to Australian customers and the rails backend is smart enough to make sure all the URLs look similar (I’ll blog about how I did that another time).

Without much time to look into thing properly I did some really nasty things on the AU squid cache to make sure it cached the pages.

Plaintext
refresh_pattern /client/graph  1440 0% 1440 ignore-no-cache ignore-reload
refresh_pattern /client/static 1440 0% 1440 ignore-no-cache ignore-reload
refresh_pattern /client/video  1440 0% 1440 ignore-no-cache ignore-reload

This is evil, breaks a whole heap of RFCs but it did the trick and got us out of a bind quickly.

A few weeks ago I moved the production site to Rails 2.0, I noticed around this time that the caching had stopped working. The client was no longer using our services as their campaign had finished so it wasn’t an urgent concern.

It seems that Rails 2.0 goes one step further to ensure that caches don’t cache content and instead of just sending

Plaintext
Cache-Control: no-cache

it now sends

Plaintext
Cache-Control: private, max-age=0, must-revalidate

I tried adding ignore-private, since if you’re breaking some aspects of the RFC you may as well break a couple more, but squid still refused to cache the content. After struggling with this for a bit I decided that the universe was trying to tell me I should actually do things properly.

So with squid set back to its defaults I went exploring how to accomplish this. Google wasn’t all that helpful at first since most Rails caching articles talk about caching to static files as most sites don’t implement reverse proxying for caching. It turns out however its fairly simple. In the appropriate actions in your controllers simply do the following.

Ruby
class VideoController < ApplicationController
  def vquence
    # Lots of code here

    expires_in 8.hours, :private => false
    render :template => "videos/vquence"
  end
end

This will send the following header and cache the page for 8 hours.

Plaintext
Cache-Control: max-age=28800

Now everything is much faster!!

Sysadmin cache, rails, squid

Reader Interactions

Comments

  1. Jauder Ho says

    22 March 2008 at 10:18 am

    Thanks for the article.

    What are you doing to handle cookies in this scenario? I’m using varnish instead of squid and I’m seeing Cache-Control being set as you said. However, looking at the cache hits, it looks like things are not being fetched from cache. I’m doing a content GET so it should be cachable.

    Reply
  2. Rich Apodaca says

    11 February 2009 at 7:12 am

    Thanks for the post! It helped me (temporarily) solve a problem with Safari and dynamically-generated images sent with send_data in Rails 2.2.2. The images would load the first time they were requests, but on reloading, Safari would hang for a few minutes, and then timeout. I could clear Safari’s cache and the reload and the image would reload.

    Using your tip (expires_in …) fixed the problem.

    Reply
  3. martin says

    22 February 2012 at 11:26 am

    hi, nice post. I like the idea of using squid as a reverse proxy for thin or mongrel, but i never configured a squid and i can not find any information on how to use squid with rails. can you give me a hint where to start?

    Reply
    • johnf says

      2 March 2012 at 8:58 am

      Hi Martin,

      That post is fairly old now and times have moved on a little. I would explore using nginx or varnish as a reverse proxy instead.

      Reply

Leave a Reply to martin Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Hit the ground running with a minimalist look. Learn More

Copyright © 2025 · Inodes Pty Ltd · Log in

  • Privacy Policy