Replacing page cache with varnish
I am finally getting somewhere with configuring varnish to run in front of typo. I just need to add code to purge the varnish cache when pages are expired and add ESI support so page can be semi cached in varnish and composed on demand. The following is the code so fare. First adding PURGE to net/http
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
require "net/http" module Net class HTTP class Purge < HTTPRequest METHOD = "PURGE" REQUEST_HAS_BODY = false RESPONSE_HAS_BODY = false end def purge(path, initheader = nil) request(Purge.new(path, initheader)) end end def HTTP.purge(path, initheader = nil) uri = URI.parse(path) new(uri.host,uri.port).start do |http| http.purge(uri.path) end end end |
Then overriding the page cache.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
module VarnishCache module Caching def self.included(base) #:nodoc: base.class_eval do include Pages end end end module Pages def self.included(base) #:nodoc: base.extend(ClassMethods) end module ClassMethods def cache_page(content, path) logger.info "VarnishCache cache_page(#{path})" content end def caches_action(*actions) logger.info "VarnishCache caches_action" end end end end |
I also had to make changes to the PageCache class zap_pages method so that it forced varnish to purge the cache
app/models/page_cache.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
def self.zap_pages(paths) logger.debug "PageCache - About to zap: #{paths.inspect}" srcs = paths.inject([]) { |o,v| o + Dir.glob(public_path + "/#{v}") } varnish_purge(paths) return true if srcs.empty? logger.debug "PageCache - About to delete: #{srcs.inspect}" trash = RAILS_ROOT + "/tmp/typodel.#{UUID.random_create}" FileUtils.makedirs(trash) FileUtils.mv(srcs, trash, :force => true) FileUtils.rm_rf(trash) end def self.varnish_purge(paths) paths.split.flatten.each do |path| uri = "http://blog.vortorus.net/#{path}" Net::HTTP.purge(uri) logger.debug "Varnish purging #{uri}" end end |
The is also the varnish vcl file changes to make purge work
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
sub vcl_recv {
# Host header check.
if (!req.http.host ~ "blog.vortorus.net") {
error 404 "Unknown virtual host";
}
if (req.request != "GET" && req.request != "HEAD") {
if (req.request == "PURGE") {
if (client.ip ~ purge) {
purge_url(req.url);
error 200 "Purged";
}
}
pipe;
}
if (req.url ~ "\.(png|gif|jpg|swf|css|js)$") {
remove req.http.cookie;
remove req.http.authenticate;
lookup;
}
# only need session for admin functions
if (req.url ~ "^/(admin|acounts)") {
pipe;
} else {
# disable Etags
remove req.http.If-None-Match;
remove req.http.cookie;
remove req.http.authenticate;
lookup;
}
}
sub vcl_hit {
deliver;
}
sub vcl_fetch {
if (req.url ~ "\.(png|gif|jpg|swf|css|js)$") {
deliver;
}
if (req.url ~ "^/(admin|acounts)") {
pass;
} else {
remove obj.http.Set-Cookie;
remove obj.http.Etag;
set obj.http.Cache-Control = "no-cache";
set obj.ttl = 7d;
deliver;
}
} |
The source for the varnish rails plugin can be found hear
# git clone git://git.vortorus.net/varnish-cache.git