Exploring methods to purge Varnish cache
I’m considering implementing Varnish at Stanford Law and have been playing with it here to understand implications and workout issues. One issue is purging pages from cache as they are modified or new pages are added. Varnish provides several methods to do this (varnishadm, telnet and http).
1. Varnishadm
Purge a specific page (front page of this blog, for example):
varnishadm -T 127.0.0.1:6082 purge req.url == "/alain/"
Result:
varnishadm -T 127.0.0.1:6082 purge.list 0 req.url == /alain/
Purge any page matching a regular expression (front page of this blog, for example):
varnishadm -T 127.0.0.1:6082 purge.url "^/alain/$"
Result:
varnishadm -T 127.0.0.1:6082 purge.list 0 req.url ~ ^/alain/$
2. Telnet
Similar to running varnishadm, except we have to open a telnet connection first:
telnet localhost 6082 purge req.url == "/alain/" 200 0
My boxes don’t accept telnet connections from the Internets so I can’t think of a scenario where I’d be talking to varnishd via telnet, so varnishadm is what I’d use at the shell or in a script.
3. HTTP
This one is probably the one that will see the most use as it is most accessible for a web based application. The only caveat is that it doesn’t support regular expressions, so just one URL at a time can be passed this way.
Will test first via telnet:
Request: telnet localhost 80 Response: Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Request: PURGE /alain/ HTTP/1.0 Host: giantdorks.org Response: HTTP/1.0 200 OK Date: Tue, 11 May 2010 02:00:00 GMT Server: Apache X-Pingback: http://giantdorks.org/alain/xmlrpc.php Vary: Accept-Encoding Connection: close Content-Type: text/html; charset=UTF-8 ... Followed by the HTML output of the page
Note that the HTTP request was “PURGE HTTP/1.0″ instead of the usual “GET HTTP/1.1″.
Now on to a more useful example. Here’s a PHP example using the built in fsockopen function, example based on the one offered at php.net:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php $fp = fsockopen("127.0.0.1", "80", $errno, $errstr, 2); if (!$fp) { echo "$errstr ($errno)<br />\n"; } else { $out = "PURGE /alain HTTP/1.0\r\n"; $out .= "Host: giantdorks.org\r\n"; $out .= "Connection: Close\r\n\r\n"; fwrite($fp, $out); while (!feof($fp)) { echo fgets($fp, 128); } fclose($fp); } ?> |
Here’s another one. Presents user with a form to supply the URL and host (virtual host). Slightly modified example pulled from varnish-cache.org:
index.html:
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 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>Purge Varnish cache</title> </head> <style type="text/css"> body { font-size: 10px; } h1 { font-weight: bold; color: #000000; border-bottom: 1px solid #C6EC8C; margin-bottom: 2em; } label { font-size: 160%; float: left; text-align: right; margin-right: 0.5em; display: block } input[type="text"] { width: 500px; } .submit input { margin-left: 0em; margin-bottom: 1em; } </style> <body> <h1>Makes Varnish purge the supplied URL from its cache</h1> <form action="vpurge.php" method="post"> <p><label>URL</label> <input type="text" name="url"></p> <p><label>HOST</label> <input type="text" name="host"></p> <p class="submit"><input value="Submit" type="submit"></p> </form> </body> </html> |
vpurge.php:
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 | <?php # get param $url = $_POST["url"]; $host = $_POST["host"]; $ip = "127.0.0.1"; $port = "80"; $timeout = 1; $verbose = 1; # inits $sock = fsockopen ($ip,$port,$errno, $errstr,$timeout); if (!$sock) { echo "connections failed $errno $errstr"; exit; } if ( !($url || $host) ) { echo "No params"; exit; } stream_set_timeout($sock,$timeout); $pcommand = "purge"; # Send command $pcommand .= ".hash $url#$host#"; put ($pcommand); put ("quit"); fclose ($sock); function readit() { global $sock,$verbose; if (!$verbose) { return; } while ($sockstr = fgets($sock,1024)) { $str .= "rcv: " . $sockstr . "<br>"; } if ($verbose) { echo "$str\n"; } } function put($str) { global $sock,$verbose; fwrite ($sock, $str . "\r\n"); if ($verbose) { echo "send: $str <br>\n"; } readit(); } ?> |
Leave a comment