1/48

HTTP Caching mit Varnish


IPC München, 24. Oktober 2016


© David Buchmann

Was ist schon wieder ein reverse proxy?

What could possibly go wrong?

httpstatusdogs.com

Überblick




HTTP Refresher

Das HTTP Protokoll

Request

1GET /path
2Accept-Encoding: text/html

Response

1HTTP/1.1 200 OK
2Content-Type: text/html
3 
4<html>...</html>

HTTP Verben

HTTP Antwort-Codes

twitter.com/stevelosh/status/372740571749572610




HTTP Cache Control

Cache Control Header

HTTP 1.1, RFC 2616, Kapitel 13.2 und 13.3

Cache Expiration

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

Cache Validation

ETag: 82901821233

If-None-Match: 82901821233

304 Not Modified

Nicht cachen

1Cache-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)

Voreingestellte Varnish Konfiguration

Varianten auseinander halten

Inhalt hängt von Request Header ab

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

Varnish macht genau das,
was du ihm sagst


Bitte genau aufpassen und gut testen

Varnish Configuration Language

VCL: Debuggen time to live

1sub vcl_backend_response {
2    set beresp.http.TTL = beresp.ttl;
3}

VCL: Debuggen cache hit / miss

01sub vcl_deliver {
02    # If X-Varnish contains only 1 id, we have
03    # a miss, if it contains more (and
04    # therefore a space), we have a hit.
05 
06    if (resp.http.X-Varnish ~ " ") {
07        set resp.http.Debug-Cache = "HIT";
08    } else {
09        set resp.http.Debug-Cache = "MISS";
10    }
11}

VCL: Zwei Applikationen

01backend default {
02    .host = "127.0.0.1"; .port = "8080";}
03backend legacy {
04    .host = "127.0.0.1"; .port = "8000";}
05 
06sub vcl_recv {
07    if (req.url ~ "^/archive/") {
08        set req.backend_hint = legacy;
09    } else {
10        set req.backend_hint = default;
11    }
12}

VCL kann vieles


Aber bitte nicht zuerst schauen, dass die Webanwendung HTTP korrekt verwendet!

Fortgeschrittene Themen

Cache Invalidierung

Die zwei harten Probleme in der Computerwissenschaft:

  1. Naming things
  2. Cache Invalidierung
  3. Off by one Fehler

Cache busting

1<link rel="stylesheet" href="/css/style.css?v1" type="text/css"/>
2...
3<script src="/js/scripts.js?v1"></script>

Explizite Cache Invalidierung

Arten der Invalidierung

Invalidierung senden

Eigene VCL für purge

01acl invalidators {
02    "localhost";
03}
04 
05if (req.method == "PURGE") {
06    if (!client.ip ~ invalidators) {
07        return (synth(405, "Not allowed"));
08    }
09    return (purge);
10}
11 
12...

Banning

01vcl_backend_response {
02    set beresp.http.X-Url = bereq.url;
03    set beresp.http.X-Host = bereq.http.host;
04}
05 
06vcl_recv {
07  if (req.method == "BAN") {
08    if (!client.ip ~ invalidators) {
09      return (synth(405, "Not allowed"));
10    }
11    ban("obj.http.X-Host ~ " + req.http.X-Host
12      + " && obj.http.X-Url ~ " + req.http.X-Url
13    );
14  }
15}



Cache Tagging

Cache Tagging

1$response->withHeader('X-Cache-Tags', 'id-42');
1ban("obj.http.x-cache-tags ~ "
2      + req.http.x-cache-tags
3);

FOSHttpCacheBundle

1/** @var $cm CacheManageer */
2$cm->tagResponse($response, array('id-42'));
3...
4$cm->invalidateTags(array('id-42'));
1use FOS\HttpCacheBundle\Configuration\Tag;
2class CommentController extends Controller {
3    /**
4     * @Tag({"comments", "'comment-'~id"})
5     */
6    public function commentAction($id)
7    // ...



Edge Side Includes

Edge Side Includes verwenden

Wie server side include, aber in Varnish:




Caching und Sessions

Strategien für Caching mit Sessions




Wrap-Up

Take-Aways

Ausblick: Code Bibliotheken

Outlook: Wie weiter?

Outlook: Caching ist nicht alles

Danke!


@dbu