Hands-on


HTTP Caching with Varnish


Bulgaria PHP Conference, September 25th, 2015


© David Buchmann

Step 1

apt-get install varnish
            

Step 1

apt-get install varnish
            

Step 2

service apache2 restart
service varnish restart
            

Step 3

What could possibly go wrong?

httpstatusdogs.com

Overview




HTTP Refresher

What is a reverse proxy again?

HTTP is simple

GET /path

HTTP/1.1 200 OK
Content-Type: text/html

<html>...</html>
            

HTTP verbs

HTTP response codes

twitter.com/stevelosh/status/372740571749572610

Tools and helpers

                wget -Sq --spider varnish.lo/solutions/expiration.php
                curl -o /dev/null -sD - varnish.lo/solutions/expiration.php
            



HTTP Cache Control

Cache control headers

HTTP 1.1, RFC 2616, Sections 13.2 and 13.3

Cache Expiration

Cache-Control: s-maxage=3600, max-age=900
Expires: Thu, 15 May 2014 08:00:00 GMT
            
  1. s-maxage
  2. max-age
  3. Expires (HTTP 1.0 - avoid!)
  4. Default to default_ttl if nothing specified

Hands on: Cache headers

curl -sD - varnish.lo/noinfo.php
curl -sD - varnish.lo/exercises/expiration.php
            

Cache validation (I)

ETag: 82901821233
            
If-None-Match: 82901821233

304 Not Modified
            

Hands on: Etag

curl -sD - varnish.lo/exercises/etag.php
curl -H "If-None-Match: abc" -sD - varnish.lo/exercises/etag.php
            

Cache validation (II)

Last-Modified: Tue, 13 May 2014 08:13:20 GMT
            
If-Modified-Since: Tue, 13 May 2014 08:13:20 GMT

304 Not Modified
            

Hands on: If-Modified-Since

curl -sD - varnish.lo/exercises/last-modified.php
curl -H "If-Modified-Since: {previous timestamp}" -sD - varnish.lo/exercises/last-modified.php
            











There are dog images too, but I won’t show the 304 one.

Validation: ETag or Last-Modified

Know your tools

Do not cache

Cache-Control: s-maxage=0, private, no-cache
            

www.varnish-cache.org/trac/browser/bin/varnishd/default.vcl?rev=3.0 (Varnish 3)
www.varnish-cache.org/trac/browser/bin/varnishd/builtin.vcl?rev=4.0 (Varnish 4)

Hands on: Do not cache

curl -sD - varnish.lo/exercises/nocache.php
            

Default Varnish behaviour

Hands on: Cookie

curl -sD - varnish.lo/cookie.php
curl -H "Cookie: x" -sD - varnish.lo/solutions/expiration.php
            

Keep variants apart

Content depending on request headers

GET /resource
Accept: application/json
            
GET /resource
Accept: text/xml
            
Vary: Accept
            

Hands on: Content negotiation

curl -sD - varnish.lo/exercises/content-negotiation.php
curl -H "Accept: application/json" -sD - varnish.lo/exercises/content-negotiation.php
            


Let’s look into Varnish

Warning!


Varnish does what you tell it


Think carefully and test thoroughly

Varnish Configuration Language

Restart Varnish like a pro

VCL: Debug hit or miss, TTL

sub vcl_backend_response {
    set beresp.http.X-TTL = beresp.ttl;
}

sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.X-Cache = "HIT";
    } else {
        set resp.http.X-Cache = "MISS";
    }
}
            

VCL: Two applications

backend default {
    .host = "127.0.0.1";
    .port = "8080";
}
backend legacy {
    .host = "127.0.0.1";
    .port = "8000";
}
sub vcl_recv {
    if (req.url ~ "^/archive/") {
        set req.backend_hint = legacy;
    } else {
        set req.backend_hint = default;
    }
}
            

VCL: Remove cookies

sub vcl_recv {
    if (req.http.Cookie) {
        if (req.url ~ "^/cache") {
            remove req.http.Cookie;
        }
    }
}
curl -H "Cookie: x" -sD - varnish.lo/solutions/expiration.php
            

Bad Practice: This is leaking knowledge about URLs to Varnish config

VCL: Custom TTL

header('X-Reverse-Proxy-TTL: 30');
C{ #include <stdlib.h>; }C
sub vcl_backend_response {
    if (beresp.http.X-Reverse-Proxy-TTL) {
        C{
            char *ttl;
            const struct gethdr_s hdr = { HDR_BERESP, "\024X-Reverse-Proxy-TTL:" };
            ttl = VRT_GetHdr(ctx, &hdr);
            VRT_l_beresp_ttl(ctx, atoi(ttl));
        }C
        unset beresp.http.X-Reverse-Proxy-TTL;
    }
}
...