HTTP Caching mit Varnish
IPC München, 24. Oktober 2016
© David Buchmann
Was ist schon wieder ein reverse proxy?
What could possibly go wrong?
- Nichts wird gecached (HTTP Headers)
- Zuviel wird gecached (also HTTP Headers)
- Redaktoren siehen Änderungen nicht (Cache Invalidierung)
- Caches werden vermischt (personalisierter Inhalt)
httpstatusdogs.com
Überblick
- HTTP refresher
- HTTP cache control
- Varnish
- Fortgeschrittene Themen
- Ausblick
HTTP Refresher
Das HTTP Protokoll
Request
GET /path
Accept-Encoding: text/html
Response
HTTP/1.1 200 OK
Content-Type: text/html
<html>...</html>
HTTP Verben
- GET
- HEAD
- POST
- PUT
- DELETE
- ...
HTTP Antwort-Codes
- 1xx hold on
- 2xx here you go
- 3xx go away
- 4xx you fucked up
- 5xx I fucked up
twitter.com/stevelosh/status/372740571749572610
HTTP Cache Control
Cache Control Header
- Cache Expiration Model
- Cache Validation Model
HTTP 1.1, RFC 2616, Kapitel 13.2 und 13.3
Cache Expiration
Cache-Control: s-maxage=3600, max-age=900
Expires: Thu, 15 May 2014 08:00:00 GMT
- s-maxage
- max-age
- Expires (HTTP 1.0 - avoid!)
- Wenn nichts angegeben: default_ttl
Cache Validation
- Hash auf der Response
- Client sendet Hash beim nächsten Request
- Server kann prüfen ob Hash geändert hat
ETag: 82901821233
If-None-Match: 82901821233
304 Not Modified
Voreingestellte Varnish Konfiguration
- Nur GET und HEAD Request werden gecached
- Requests mit cookies / authorization header werden nie gecached
- Responses mit set-cookie werden nie gecached
-
Cached nur safe Responses (status 200, 203, 300, 301, 302, 307, 404, 410)
Varianten auseinander halten
Inhalt hängt von Request Header ab
GET /resource
Accept: application/json
GET /resource
Accept: text/xml
Vary: Accept
Varnish macht genau das,
was du ihm sagst
Bitte genau aufpassen und gut testen
Varnish Configuration Language
- Lesen und schreiben von Headern
- If Konditionen, aber keine Schleifen
- Funktionen: Reguläre Ausdrücke, Invalidierung
- Keine Rückgabewerte, nur Status Änderungen
- Keine Variablen, Information persistieren nur in Headern
- Inline C code
- //, # und /* foo */ für Kommentare
VCL: Debuggen time to live
sub vcl_backend_response {
set beresp.http.TTL = beresp.ttl;
}
VCL: Debuggen cache hit / miss
sub vcl_deliver {
# If X-Varnish contains only 1 id, we have
# a miss, if it contains more (and
# therefore a space), we have a hit.
if (resp.http.X-Varnish ~ " ") {
set resp.http.Debug-Cache = "HIT";
} else {
set resp.http.Debug-Cache = "MISS";
}
}
VCL: Zwei Applikationen
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 kann vieles
- Hinzufügen, ändern und löschen von Headern in Request und Response
- Entscheiden ob und wie gecached wird
- Request URLs umschreiben
Aber bitte nicht zuerst schauen, dass die Webanwendung HTTP korrekt verwendet!
Fortgeschrittene Themen
- Cache Invalidierung
- Cache Tagging
- Edge Side Includes
- Caching und Sessions
Cache Invalidierung
Die zwei harten Probleme in der Computerwissenschaft:
- Naming things
- Cache Invalidierung
- Off by one Fehler
Cache busting
- Sehr lange cache lifetime für Assets
- ?version an Asset Links anhängen
- Der Query String führt zum Cache miss
<link rel="stylesheet" href="/css/style.css?v1" type="text/css"/>
...
<script src="/js/scripts.js?v1"></script>
Explizite Cache Invalidierung
- Lange cache lifetime in Varnish
- Nachrichten an Varnish um gezielt gecachte URLs zu Invalidieren
- Änderungen die sich nicht sauber erkennen lassen: Kurze lifetime
Arten der Invalidierung
- Purge: URL und alle Varianten
- Refresh: Genau diesen Request erneuern, wärmt Cache wieder auf
- Ban: breite Invalidierung mit Regulären Ausdrücken
Invalidierung senden
- varnishdm Kommandozeilen Programm
- Eigene VCL und Web Requests
- Messaging: Wenn die Varnish Server nicht bekannt sind (cloud)
Eigene VCL für purge
acl invalidators {
"localhost";
}
if (req.method == "PURGE") {
if (!client.ip ~ invalidators) {
return (synth(405, "Not allowed"));
}
return (purge);
}
...
Banning
- Reguläre Ausdrücke
- Geht für beliebige Header, nicht nur Pfad
vcl_backend_response {
set beresp.http.X-Url = bereq.url;
set beresp.http.X-Host = bereq.http.host;
}
vcl_recv {
if (req.method == "BAN") {
if (!client.ip ~ invalidators) {
return (synth(405, "Not allowed"));
}
ban("obj.http.X-Host ~ " + req.http.X-Host
+ " && obj.http.X-Url ~ " + req.http.X-Url
);
}
}
Cache Tagging
Cache Tagging
- Eigener Header mit id von jedem Inhalts-Element
- BAN Request für den Header wenn Element geändert hat
$response->withHeader('X-Cache-Tags', 'id-42');
ban("obj.http.x-cache-tags ~ "
+ req.http.x-cache-tags
);
FOSHttpCacheBundle
/** @var $cm CacheManageer */
$cm->tagResponse($response, array('id-42'));
...
$cm->invalidateTags(array('id-42'));
use FOS\HttpCacheBundle\Configuration\Tag;
class CommentController extends Controller {
/**
* @Tag({"comments", "'comment-'~id"})
*/
public function commentAction($id)
// ...
Edge Side Includes
Edge Side Includes verwenden
Wie server side include, aber in Varnish:
- URLs im Inhalt auf Inhaltsteile
- Varnish hohlt und cached die Teile separat
- Individuelle Caching Regeln pro Teil
- z.B. nur gewisse Teile hängen von Cookie ab, unterschiedliche TTL, ...
Caching und Sessions
Strategien für Caching mit Sessions
- Session vermeiden, beenden wenn nicht mehr benötigt
- Cache lookup trotz Cookies
- Response Header um caching von Cookie spezifischen Seiten zu verhindern
- Vary auf dem Cookies Header
- User Context: Caching pro Berechtigungsgruppe
Wrap-Up
Take-Aways
- Varnish kann viel
- Varnish ist gefährlich
- KISS VCL!
- Zuerst das HTTP Verhalten der Webanwendung korrigieren
- Verstehe was du machst, teste was du machst
Ausblick: Code Bibliotheken
- Varnish plugins (vmods) für Dinge wie basic authentication
- Frameworks für bessere Modellierung von HTTP request/response, z.B. PSR-7
- FOSHttpCache: Invalidierung, integration tests mit Varnish
- Symfony Anwender sollten sich das FOSHttpCacheBundle anschauen
Outlook: Wie weiter?
- Monitoring was Varnish macht
- Verbessern der cache hit Ratio
- Varnish Tutorials: varnish-cache.org
Outlook: Caching ist nicht alles
Danke!
@dbu