Aus Linux-Magazin 05/2019

Webapplikationen mit Varnish Cache beschleunigen

© Fernando Cortés, 123RF

Liefert eine Webanwendung ihre Pages zu langsam aus, springen die Nutzer recht bald ab. Mit Varnish Cache spannt der Admin ein paar zusätzliche Pferde vor den Karren. Was Varnish Cache anders macht und wie ein Admin damit im Rennen um die beste Performance vordere Plätze belegt, verrät der Artikel.

Die meisten erfolgreichen Webapplikationen wachsen organisch und kommen irgendwann an den Punkt, an dem im System ein Geschwindigkeitsengpass entsteht. Zwar können Admins lange darüber philosophieren, warum so etwas passiert und wann sie etwas hätten dagegen tun können, aber da liegt das Kind bereits im Brunnen.

Webseiten, die zu langsam sind, haben in der Regel höhere Absprungraten. Mitunter erleiden sie auch unfreiwillige Denial-of-Service-Attacken durch normale Besucher, die bei zu langen Ladezeiten gern auf Reload klicken. Je nach Programmiersprache und verwendetem Framework passiert dies mal früher, mal später – beide darf der Entwickler oft nicht selbst auswählen, weil etwa das berufliche Umfeld sie vorgibt.

Der Klassiker

Abseits aller Optimierung von Cache-Funktionen im Stack sollte der Admin auch immer Ausschau nach klassischen Programmierfehlern halten. Nicht selten verstecken sich in altem Code kleine bis große Minenfelder. Diese zu räumen belohnt der Stack mit deutlich mehr Performance, als sie alle im Nachgang implementierten Caches bieten.

Wird eine Webseite zu langsam und liegt der Engpass beim Webapplikations-Server, der den HTML-Code zu langsam generiert, gilt als klassische Lösung schnellere oder mehr Hardware. Läuft die Webapplikation bei Hostern wie AWS oder Heroku, löst der Admin das Problem mit der Kreditkarte. Ist letztere ausgereizt, die Cloud keine Option oder die Problemlösungs-Ehre angegriffen, beginnt die Suche nach besseren Lösungen.

Whodunit

Um ein Performance-Problem zu verstehen, zeichnet der Admin erst einmal die Kette von der Abfrage des Webbrowsers bis zum Datensatz nach.

Webapplikationen speichern Daten meist in einer SQL-Datenbank. Die Webanwendung, oft in PHP, Python oder Ruby geschrieben, schnappt sich diese Daten und macht eine Webseite mit HTML-Code daraus. Diese liefert ein Webserver (Apache oder Nginx) an den Webbrowser aus. Die ganze Einheit bis zum Webserver heißt auch Backend (Abbildung 1).

Abbildung 1: Wenn es im Backend klemmt, sucht der Admin bei den verschiedenen beteiligten Komponenten nach Performancebremsen.

Abbildung 1: Wenn es im Backend klemmt, sucht der Admin bei den verschiedenen beteiligten Komponenten nach Performancebremsen.

Als Erstes optimiert der Admin den Datenbankserver und, wenn es sich um ein SQL-System handelt, die SQL-Abfragen. Hat er diesen Weg ausgereizt, widmet er sich dem Caching in der Applikation, oft in Form von Fragment Caching. Er sorgt dafür, dass der Cache Teile des von der Webapplikation erstellten HTML-Codes in einem schnellen Key-Value-Store wie Redis [1] speichert, aus dem ihn die Webapplikation dann abruft.

Zusätzlich arbeitet der Admin auf Wunsch auch mit HTTP Caching [2]. Dabei sagt die Webapplikation dem Webbrowser, dass die gerade ausgelieferte HTML-Seite oder das Bild für eine bestimmte Zeit gültig sind. Der Webserver reicht diese Informationen unverändert weiter. Hierfür lässt sich übrigens auch ein E-Tag [3] einsetzen. Damit fragt dann umgekehrt der Browser den Webserver beim wiederholten Besuch, ob die lokal gespeicherte Seite noch relevant ist.

Flinker Makler

Wer das alles verstanden hat und aktiv benutzt, der stolpert am Ende zwangsweise über den Varnish HTTP Cache [4]. Dieser lebt als Reverse-Proxy zwischen dem Webserver und dem Internet. Das klingt zunächst unspektakulär, schließlich lassen sich auch ein Nginx oder Apache Webserver als Reverse-Proxy konfigurieren. Varnish ist jedoch sehr viel intelligenter. Er lässt sich über die sehr performante Varnish Configuration Language (VCL, [5]) feingranular programmieren und konfigurieren.

Varnish zielt dabei in erster Linie auf einen Einsatz für Webseiten mit hohem Traffic ab. Natürlich funktioniert der Reverse-Proxy auch für eine kleine Webseite, aber der initiale Aufwand rechnet sich dann vermutlich eher nicht. Das Ziel von Varnish ist, möglichst viele Anfragen selbstständig zu beantworten. Erst wenn er nicht mehr weiterkommt, greift er auf den Webserver oder den Webapplikations-Server dahinter zu.

Varnish kann nichts, was nicht andere Elemente in der Kette, also der Webserver und der Webapplikations-Server, auch können. Tatsächlich beherrscht Varnish im direkten Vergleich mit dem Applikationsserver nur sehr wenige Dinge – die erledigt der Reverse-Proxy aber richtig, also richtig schnell, gern auch als Teil eines Clusters und in einem weltweit verteilten Setup.

Listing 1

Redirect von HTTP auf HTTPS

01        sub vcl_recv {
02        if (std.port(server.ip) == 80 && req.http.host ~ "^(?i)example.com") {
03               set req.http.x-redir = "https://" + req.http.host + req.url;
04               return(synth(850, "Moved permanently"));
05        }
06        }
07
08        sub vcl_synth {
09        if (resp.status == 850) {
10               set resp.http.Location = req.http.x-redir;
11               set resp.status = 301;
12               return (deliver);
13        }
14        }

Da Varnish dabei wesentlich weniger Ressourcen verbraucht und schneller arbeitet, beschleunigt der Proxy das gesamte System. Daher arbeiten vermutlich auch die meisten CDN-Anbieter (Content Delivery Network) mit Varnish. Sie wollen ihre Daten kontinentübergreifend möglichst fix ausliefern. Wie das geht, zeigen ein paar Beispiele in der erwähnten Varnish Configuration Language, in denen Varnish seine Geschwindigkeit ausspielt.

Einen Redirect von HTTP auf HTTPS einrichten

Da im Zeitalter von HTTP/2 die Datenübertragung via HTTPS der Standard ist, braucht die Webseite einen Redirect von HTTP auf HTTPS (Listing 1). Der anfragende Webbrowser bekommt in der Folge als Antwort einen »301 Redirect« auf die neue HTTPS-URL.

Cache Time-to-Live (TTL)

Inhalte zu cachen und diese später bei identischen Anfragen auszuliefern ist das Brot-und-Butter-Geschäft von Varnish. Soll der Reverse-Proxy eine Webseite nach dem ersten Mal stets weitere fünf Minuten lang statisch ausliefern, erreicht der Admin dies mit dem simplen VCL-Codeschnipsel aus Listing 2.

Listing 2

Wiedervorlage

01        sub vcl_backend_response {
02          set beresp.ttl = 5m;
03        }

Keinen Cache für eingeloggte User anlegen

Zeigt eine Webseite angepasste Inhalte für einen eingeloggten Nutzer an, darf Varnish diese Seite natürlich nicht cachen. In diesen Fällen kann es auf bestimmte, von der Webapplikation gesetzte Cookies reagieren. Im Beispiel von Listing 3 heißen das Cookie »logged_in« und die zugehörige Domain »example.com«.

Listing 3

Cookie für angemeldete Nutzer

01        sub vcl_recv
02        {
03        if ((req.http.host ~ "example.com" &&
04               req.http.Cookie == "logged_in")
05        {
06               return (pass);
07        }
08
09        unset req.http.Cookie;
10        }

Verfügbarkeit auch ohne Backend

Wird das Backend sehr langsam oder fällt ganz aus (beispielsweise durch ein Update der Software oder einen Denial-of-Service-Angriff), soll Varnish die vorher gültige statische Webseite dennoch weiterhin ausliefern.

In der Konfiguration von Listing 4 überprüft Varnish alle drei Sekunden, ob das Backend »127.0.0.1:8080« noch lebt und ob die Antwort vom Backend weniger als 50 ms benötigt. Falls dies nicht der Fall ist, liefert Varnish den alten Cache für maximal zwölf Stunden weiter aus.

Listing 4

Pulsmesser

01        backend default {
02        .host = '127.0.0.1';
03        .port = '8080';
04        .probe = {
05               .url = "/";
06               .timeout = 50ms;
07               .interval = 3s;
08               .window = 10;
09               .threshold = 8;
10               }
11        }
12
13        set beresp.grace = 12h;

Veränderungen on the Fly

Der Reverse-Proxy liefert aber nicht nur Webseiten oder andere Ressourcen eins zu eins aus, sondern modifiziert diese auch im Vorübergehen. Die Software ändert oder löscht Cookies dynamisch und passt HTTP-Header an.

Varnish speichert auch Teile der Webseite zwischen und lädt andere Teile bedarfsabhängig vom Backend. So bezieht die Software in einem Onlineshop die Navigation mit den Nutzerdaten und dem Einkaufskorb dynamisch vom Backend und liest die Darstellung des aktuellen Produkts aus dem Cache. Den dynamischen Teil injiziert Varnish dann in den statischen Teil.

Kompression

Die durch Varnish gewonnene Geschwindigkeit nützt nichts, wenn der Transport die übertragenen Textdateien nicht komprimiert. Varnish unterstützt Gzip per Default, das moderne Brotli [6] aber noch nicht out of the Box.

Einer der Gründe dafür ist, dass die Kompression eigentlich auf dem Webserver passieren sollte, da Varnish ein reiner Cache ist. Wenn der Webserver (Nginx oder Apache) die Kompression vornimmt, kann Varnish diese Dateien allerdings auch eins zu eins als Cache weitergeben. In dieser Kombination darf dann auch die optimale Brotli-Kompression zum Einsatz kommen.

Wer alles noch weiter optimieren möchte, kann statische Dateien für den Webserver auch offline komprimieren. Das geht für Gzip mit Zopfli [7] und bei Brotli mit dem Level 10. Beides ist aber sehr CPU-intensiv und dauert relativ lange. Deshalb gelingt dies nur bei einer Offline-Optimierung der Inhalte.

Fazit

Wenn ein Nginx oder ein Apache ein VW Golf sind, dann ist Varnish ein Bugatti Veyron. Zwar passen in den Golf die ganze Familie und auch noch der Hund, zudem sind der Ölwechsel und die Reifen viel billiger. Doch egal wie sehr der Admin den Golf auch aufmotzt, er wird nie so schnell wie ein Bugatti.

Der Autor

Stefan Wintermeyer ist Consultant, Trainer und Buchautor für die Themen Ruby on Rails, Phoenix und Webperformance: https://www.wintermeyer-consulting.de.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 3 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Nach oben