Performance für inhaltsreiche Webseiten steigern

Varnish und der Vary Header: Dynamische Inhalte effizient cachen
1 Kommentar

Das Cachen von Webseiten ist ein Thema, das leider oft zu spät mit in die Konzeption einbezogen wird. Wenn man sich schon im Vorhinein ein paar Gedanken zum Thema macht, kann man auch auf äußerst dynamischen Webseiten ungeahnte Performance erreichen.

Die Erinnerung an die Webseitenerstellung in den alten Zeiten kann ein angenehmes Gefühl auslösen: Man erstellte ein paar HTML-Dateien, dazu noch ein paar Bilder sowie ein Stylesheet, und schob das Ganze per FTP auf einen Server. Fertig war eine Webseite, die sogar noch ziemlich performant war! Doch so einfach das damals auch gewesen sein mag, würde man mit diesen schlussendlich doch sehr bescheidenen Möglichkeiten die Anforderungen heutiger moderner Projekte wohl nicht mehr erfüllen können.

Der Kunde möchte seine Webseite selbst verwalten können, deshalb setzt man heute üblicherweise Content Management Systeme (CMS) ein, die im Hintergrund noch mit einer Datenbank kommunizieren. Der ganze Stack ist jetzt schon um einiges komplizierter und auch langsamer geworden. Mittlerweile sind Webseiten oft schon sehr dynamisch. Es werden die letzten Artikel auf der Startseite dargestellt, der Name des eingeloggten Benutzers wird irgendwo angezeigt, oder man muss gar einen Newsfeed programmieren, der sowieso für jeden Benutzer anders aussieht. Und all das auf Kosten der Performance.

Werkzeuge wie Varnish versprechen hier Abhilfe. Bei Varnish handelt sich um einen Cache für dynamische Webseiten mit viel Inhalt. Anstatt für jeden Request wieder die PHP-Applikation aufzurufen, zeitaufwendige Datenbankzugriffe auszuführen und das Ganze erst mit einer Templatesprache in HTML übersetzen zu lassen, versucht Varnish, sich die Antwort vom Request zu merken und liefert diese im Idealfall direkt aus dem Arbeitsspeicher aus. Das ist natürlich unvergleichbar viel schneller, weshalb es sich wirklich auszahlt, sich mit diesem Thema genauer auseinanderzusetzen.

Caching 101

Abhängig vom Betriebssystem kann man Varnish auf verschiedene Arten installieren und starten. Viele Linux-Distributionen bieten ein Package für Varnish an, wobei meist noch die Version 5.2 verwendet wird, auf die sich auch dieser Artikel bezieht. Nachdem man das Package erstellt hat, kann man Varnish entweder mit einem Service-Manager wie systemd starten oder man benutzt einfach das varnishd-Kommando auf der Kommandozeile.

Varnish setzt auf das HTTP-Protokoll. Das bedeutet, dass man es vor jede Applikation schalten kann, die über HTTP kommuniziert. Unter anderem spielt es keine Rolle, welche Programmiersprache oder welcher Webserver hinter Varnish läuft. Wir nutzen diesen Vorteil aus, indem wir einfach den PHP-internen Webserver nutzen. Der PHP-interne Webserver ist zwar nicht für den Einsatz in Produktionsumgebungen gemacht, allerdings kann er ohne viel weniger Konfigurationsaufwand benutzt werden.

Angenommen, der folgende Inhalt liegt als index.php im Verzeichnis, auf dem man sich gerade in der Kommandozeile befindet:

<?php
sleep(1);
echo 'War das anstrengend...';

Hier handelt es sich um ein sehr vereinfachtes Beispiel. Man kann aber annehmen, dass in einer realistischen Webanwendung, in der sehr viele Files eingelesen sowie Datenbankabfragen abgeschickt und Templates gerendert werden, durchaus einige Sekunden zum Erstellen der Antwort vergehen können. Dieses Beispiel kann man mit dem folgenden Kommando unter Benutzung des PHP-internen Webservers bereitstellen: php -S localhost:8000. Danach kann man in einem beliebigen Webbrowser localhost:8000 öffnen und sieht, wie sich der PHP-Prozess nach einer Sekunde beschwert, dass Schlafen ganz schön anstrengend sei. In diesem Beispiel fällt natürlich sofort auf, dass der schlussendliche Inhalt eigentlich immer der gleiche ist, unabhängig davon, wann diese Datei aufgerufen wird. Das heißt, hier würde sich Caching sehr anbieten. Wenn man sich für Varnish entscheidet, muss man eine Konfigurationsdatei bereitstellen, die in diesem Beispiel phpmagazin.vcl heißt (Listing 1).

vcl 4.0;
backend default {
    .host = "localhost";
    .port = "8000";
}

Mit dem Schlüsselwort backend teilt man Varnish mit, bei welchem Host und welchem Port sich die eigentliche Webapplikation befindet. Danach kann man Varnish mit folgendem Kommando auf der Kommandozeile starten: varnishd -a localhost:8080 -f /etc/varnish/phpmagazin.vcl -s malloc,64M -F
Achtung: Dieses Kommando muss bei manchen Systemen als root-Benutzer bzw. mit sudo ausgeführt werden.

International PHP Conference

Entwickler – das verlorene Handbuch

by Stefan Priebsch (thePHP.cc)

My browser does what?

by Joel Lord (Red Hat OpenShift

Jetzt läuft Varnish auf Port 8080 und man bekommt die gleiche Antwort wie vorhin, wenn man localhost:8080 öffnet. Der Request dauert immer noch genauso lange wie vorher, allerdings beinhaltet die Response jetzt einen HTTP-Header namens Age, der angibt, wie viele Sekunden die Response schon im Cache liegt. Der Wert dieses Headers ist 0, wenn es sich um einen Cache Miss handelt, also Varnish bei der eigentlichen Webapplikationen nachfragen musste. Momentan verbessert sich die Antwortzeit auch nach erneutem Laden nicht. Der AgeHeader behält seinen Wert, weil Varnish nicht weiß, ob die Seite gecacht werden darf. Es könnte sich um eine sehr dynamische Nachrichtenseite handeln, bei der jede Sekunde neue Inhalte ausgespielt werden. Um Varnish zu erklären, wie lange die Seite gecacht werden darf, setzen wir auf den HTTP-Request-Header namens Cache-Control. In Listing 2 wird Varnish die Response für zehn Sekunden aus seinem eigenen Cache liefern.

<?php
header('Cache-Control: public, max-age=0, s-maxage=10');

sleep(1);
echo 'War das anstrengend...';

Bevor die eigentliche Ausgabe getätigt wird, setzt die header-Methode von PHP einen HTTP-Header. Man muss dabei beachten, dass der Aufruf der header-Methode nur funktioniert, wenn davor noch keinerlei Inhalt ausgegeben wurde. Der Cache-Control-HTTP-Header hat drei Direktiven. Mit public sagt man aus, dass diese Antwort von allen Caches gecacht werden darf. Im Gegensatz dazu gibt es auch noch die private-Direktive, die das Cachen nur für private Caches erlaubt. Ein privater Cache ist ein Cache, der Inhalte nur für einen einzelnen Nutzer speichert. Dabei handelt es sich im Normalfall um den Browsercache. Im Gegensatz dazu gibt es Proxy-Caches, die gerne in großen Unternehmen zwischen dem eigenen Netzwerk und dem Internet geschaltet werden. Aber auch Varnish stellt eine Art Proxy-Cache dar, genauer gesagt handelt es sich dabei um einen Reverse Proxy. Wenn also die private-Direktive verwendet wird, dann dürfen nur Caches für einen einzelnen Benutzer – wie zum Beispiel der Browsercache – diese Antwort speichern. Da der Inhalt auch von Varnish gecacht werden soll –ein Cache, der für mehrere Benutzer gilt – muss die public-Direktive verwendet werden.

Die nächsten zwei Direktiven hängen auch mit der Unterscheidung von öffentlichem und privatem Cache zusammen. Beide Direktiven geben an, für wie viele Sekunden der Inhalt als gültig betrachtet werden soll. Der einzige Unterschied ist, dass die max-age-Direktive für private Caches und die s-maxage-Direktive für öffentliche Caches gedacht ist. Für das gewählte Beispiel ergibt es also Sinn, max-age auf 0 zu setzen, da ansonsten auch der Browser die Inhalte cacht und das beim Testen etwas lästig sein könnte. Die s-maxage-Direktive wird dann von Varnish ausgelesen und als Cache-Lifetime verwendet.

Wenn die Seite jetzt wieder neu geladen wird, kommt sie noch immer nicht aus dem Cache. Aber bei einem weiteren Neuladen sollte sich die Antwortzeit dramatisch verbessern, zumindest für die Cache-Lifetime von zehn Sekunden. Außerdem sollte sich jetzt auch der Wert des Age-Headers erhöht haben. Falls das nicht funktionieren sollte, könnte das an den Cookies, die für den URL hinterlegt sind, liegen. Varnish cacht nämlich keine Seiten, die Cookies beinhalten, weil die Cookies einen Effekt auf die Antwort haben könnten. Das ist auf den ersten Blick etwas unpraktisch, ergibt aber Sinn. Wie man dieses Verhalten umgehen kann, wird später in diesem Artikel erklärt.

Custom-HTTP-Header

Mit dem vorherigen Beispiel wurde schon ein bisschen die Frage der Cacheinvalidation angeschnitten. Dabei geht es darum, ab wann der Cache nicht mehr „fresh“ ist, also Varnish eine neue Anfrage schicken sollte. Genau das wurde vorher mit der s-maxage-Direktive im Cache-Control-Header definiert. Nach Ablauf der definierten zehn Sekunden wird der Cache dann stale, was so viel bedeutet wie veraltet.

Aber mit der oben angedeuteten Variante gibt es ein großes Problem: Die Kontrolle des Cache wird aus der Hand gegeben. Die s-maxage-Direktive wird nämlich auch von anderen Proxy-Caches verwendet, auf die man keinen Zugriff hat – und von denen es im verteilten Internet auch so viele gibt, dass es wirklich nicht praktikabel wäre, über alle Bescheid zu wissen. Somit hat man für die definierte Cache-Lifetime keine Möglichkeit, den Cache zu leeren. Deshalb ist es ratsam, diese Zeitspannen relativ kurz zu halten. Im Idealfall hat man niedrige Cache-Lifetimes für die max-age– und s-maxage-Direktiven, um möglichst viel Kontrolle darüber zu behalten. Allerdings ist das für die Performance von Varnish nicht optimal. Besonders elegant wäre es, wenn man nur für den Reverse Proxy eine höhere Cache-Lifetime ansetzten könnten, weil man dort im Notfall immer noch den Cache von Hand bzw. von der Applikation selbst ausleeren könnte.

Der HTTP-Standard sieht nichts in die Richtung vor, aber mit dem Custom-HTTP-Header kann man selbst eine Lösung bauen, die diese Funktion übernimmt. Zuerst muss man dafür einen eigenen Header definieren, der die Cache-Lifetime für den Reverse Proxy hält (Listing 3). Diesen Header kann man zusätzlich zu dem eigentlichen Caching-Header mit einer viel höheren Cache-Lifetime setzen. Allerdings ergibt es Sinn, diese Cache-Lifetime beim Testen noch niedriger zu halten.

<?php
header('Cache-Control: public, max-age=0, s-maxage=10');
header('X-Reverse-Proxy-TTL: 30');

sleep(1);
echo 'War das anstrengend...';

Mit einem weiteren Aufruf der header-Funktion setzen wir einen Wert, der nur für den Reverse Proxy bestimmt ist. Wenn man jetzt wieder die Seite localhost:8000 (also ohne Varnish) öffnet und mittels der Entwicklerwerkzeuge im Browser die HTTP-Header anschaut, sollte man den X-Reverse-Proxy-TTL-Header sehen. Die Idee ist, dass Varnish diesen Header nachher ausliest und den Wert als Cache-Lifetime verwendet. Außerdem soll der für den Client nutzlose X-Reverse-Proxy-TTLHeader von der Response entfernt werden, bevor die Antwort verschickt wird, um ein paar Bytes zu sparen. Dafür muss man die VCL-Datei editieren (Listing 4). In VCL gibt es neben dem Schlüsselwort backend auch das Schlüsselwort sub, mit dem man eine Funktion definiert. Es gibt einige besondere Funktionen, deren Verhalten man sich wie ein Ereignis vorstellen kann, denn diese werden zu gewissen Zeitpunkten in einem Anfragezyklus aufgerufen. Die Funktion, die hier gebraucht wird, heißt vcl_backend_response und wird ausgeführt, nachdem die Antwort vom PHP Backend an Varnish ausgeliefert wird.

vcl 4.0;

C{
  #include 
}C

backend default {
  .host = "localhost";
  .port = "8000";
}

sub vcl_backend_response {
  if (beresp.http.X-Reverse-Proxy-TTL) {
    C{
      const 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;
  }
}

Mit der Variable beresp in der vcl_backend_response-Funktion kann auf die Antwort vom PHP Backend zugegriffen werden. Mit http kann man auf alle HTTP-Header zugreifen, auch auf den X-Reverse-Proxy-TTLHeader, aus dem hier besprochenen Beispiel. Mit einem if kann man überprüfen, ob dieser Header gesetzt ist. Danach soll der Wert von diesem Header als Cache-Lifetime gesetzt werden. Es gibt zwar die Variable beresp.ttl, allerdings kann man diese nur auf absolute Werte und vor allem nicht dynamisch setzen. Als Ausweg kann man ein paar Zeilen C-Code zwischen C{ und }C schreiben. Wer nun an dieser Stelle Kopfweh aufgrund von Pointern, Stringterminierungen und dergleichen bekommt, dem sei gesagt: Höchstwahrscheinlich bleibt es bei diesen paar Zeilen. Nach dem C-Fragment kommt noch ein unset-Befehl, mit dem man den Header ohne jegliche weitere Funktion löschen kann.

Nach dem Editieren der VCL-Datei muss man Varnish neu starten. Da im aktuellen Stand auch noch C verwendet wird, muss man jetzt auch das vcc_allow_inline_c-Flag auf on setzen:

varnishd -a localhost:8080 -f ~/Development/phpmagazin/phpmagazin.vcl -s malloc,64M -F -p "vcc_allow_inline_c=on"

Wird die Seite nun ein paarmal neu geladen, kann man beobachten, dass der Age-Header auch über die definierten zehn Sekunden vom Cache-Control-Header geht und die Seite nach den dreißig Sekunden vom X-Reverse-Proxy-TTL-Header neu geladen wird. Um den Inhalt im Cache vor Ablauf dieser Zeitspanne löschen zu können, wird im Normalfall die nicht standardisierte PURGE-HTTP-Methode verwendet die in der vcl_recv-Funktion abgefangen werden und den Wert purge zurückliefern muss (Listing 5).

acl invalidators {
  "localhost";
}

sub vcl_recv {
  if (req.method == "PURGE") {
    if (!client.ip ~ invalidators) {
      return (synth(405, "Not allowed"));
    }
    return (purge);
  }
}

Die Variable req stellt die HTTP-Anfrage dar und erlaubt uns mittels method die HTTP-Methode abzufragen. Wenn diese PURGE sein sollte, wird zuerst überprüft, ob die Client-IP den Cache invalidieren darf, bevor wirklich purge zurückgegeben und der Cache gelöscht wird. Nachdem man z.B. mit curl die folgende Anfrage abschickt hat, sollte die Seite wieder eine Sekunde laden, bevor sie wieder gecacht wird:

curl -X PURGE localhost:8080

Variieren von Antworten mit dem Vary Header

Die bis jetzt besprochenen Technologien stellen die Grundlage für das Finale dieses Artikels dar. Es geht darum, verschiedene Inhalte auf dem gleichen URL für unterschiedliche Nutzer auszuspielen. Im Sulu CMS haben wir dieses Feature Audience Targeting genannt, weil es möglich ist, gewisse Zielgruppen unterschiedlich anzusprechen. Dabei war es uns sehr wichtig, dass der User nicht eingeloggt sein muss, sondern anhand anderer Kriterien einer Zielgruppe zugeteilt werden kann. Dabei kommen natürlich alle HTTP-Header in den Sinn, also z.B. welcher Browser wird vom Nutzer verwendet. Aber der interessanteste Punkt ist immer noch der URL – ist der Nutzer auf einer Landingpage gelandet? Beinhaltet der URL einen gewissen Queryparameter, anhand dessen man auf einen Newsletter schließen kann? Das sind sehr wertvolle Informationen, um seine Nutzer in vordefinierte Zielgruppen einzuteilen. In Sulu treiben wir das Ganze noch auf die Spitze, indem der Contentmanager zum einen Zielgruppen mit einem Regelwerk selbst definieren kann. Anschließend kann er beim Aggregieren von Seiten auf einer Übersichtsseite konfigurieren, dass die Zielgruppe beim Ausspielen dieser Seiten berücksichtigt werden soll.

Ein ähnliches Set-up dient als Grundlage für das folgende Beispiel: Es wird eine Rezeptseite angenommen, die über eine Startseite verfügt, auf der Rezepte nach den Vorlieben des Benutzers dargestellt werden. Um den Benutzer in eine Zielgruppe einzuteilen, gibt es zwei Landing pages: Eine für vegetarisches Essen und eine für Essen mit Fleisch.

Der Benutzer wird beim ersten Besuch in eine der folgenden Zielgruppen eingeteilt: „Fleischesser“, „Vegetarier“ oder „Unentschiedener“. Varnish soll für alle drei Zielgruppen einen separaten Cacheeintrag haben und die richtige Variante ausspielen. Außerdem sollte gleich beim ersten Request die richtige Variante ausgespielt werden, wenn eine Zielgruppe bestimmt werden kann.

Es gibt also zwei neue Dateien, vegetarisch.php und fleisch.php, die Inhalte für die jeweilige Art von Gerichten ausspielt. Die Datei vegetarisch.php:

<?php
  header('X-Reverse-Proxy-TTL: 30');
  echo 'Vegetarische Köstlichkeiten!';

Die Datei fleisch.php

<?php
  header('X-Reverse-Proxy-TTL: 30');
  echo 'Gerichte mit Fleisch';

An diesen beiden Dateien ist erst einmal nichts Besonderes. Die Logik hinter dem Bestimmen der Zielgruppe liegt an einer anderen Stelle, nämlich in der Datei zielgruppe.php (Listing 6).

<?php
if ($_SERVER['HTTP_X_ORIGINAL_URL'] === '/vegetarisch.php') {
  header('X-Zielgruppe: vegetarier');
  exit;
}

if ($_SERVER['HTTP_X_ORIGINAL_URL'] === '/fleisch.php') {
  header('X-Zielgruppe: fleischesser');
  exit;
}

header('X-Zielgruppe: unentschiedener');

Wir werden Varnish später so konfigurieren, dass diese Datei zum Bestimmen der Zielgruppe aufgerufen wird, falls der Benutzer noch keiner Zielgruppe zugeteilt ist. Varnish wird der Anfrage an diese Datei einen X-Original-Url-Header mitschicken, anhand dessen wir die Zielgruppe bestimmen. Anschließend setzt Varnish den X-Zielgruppe-Header mit dem entsprechenden Wert.

Um dieses Vorhaben umzusetzen, werden zwei Funktionen von Varnish benötigt: vcl_recv, die vorhin schon für das Purgen von Inhalten verwendet wurde, und zusätzlich die Funktion vcl_deliver, die aufgerufen wird, bevor die Antwort von Varnish an den Browser zurückgeschickt wird. Da der Browser mit dem selbst definierten X-Zielgruppe-Header leider nichts anzufangen weiß, muss man sich etwas anderes überlegen, damit sich der Browser die Zielgruppe merkt. Dafür bietet sich ein Cookie an, den man auch mittels VCL setzen kann. Allerdings cacht Varnish wie bereits beschrieben keine Anfragen, die einen Cookie beinhalten, weshalb üblicherweise der Inhalt des Cookies auf einen HTTP-Header umgeschrieben und dann von der Anfrage in der vcl_recv Funktion gelöscht wird.

Um zwei Anfragen pro Browseranfrage ausführen zu können, gibt es den Rückgabewert restart. Dieser erlaubt es, nachdem der Request angepasst wurde, diesen nochmals abzusenden. Gleichzeitig erhöht dieser Rückgabewert den Zähler restarts auf der Variable req. All das macht sich das VCL-Skript in Listing 7 zunutze.

sub vcl_recv {
  /* Code für das Purgen von vorhin */
  if (req.http.Cookie ~ "zielgruppe") {
    set req.http.X-Zielgruppe = regsub(req.http.Cookie, ".*zielgruppe=([^;]+).*", "\1");
  } elseif (req.restarts == 0) {
    set req.http.X-Original-Url = req.url;
    set req.url = "/zielgruppe.php";
  } elseif (req.restarts > 0) {
    set req.url = req.http.X-Original-Url;
    unset req.http.X-Original-Url;
  }

  unset req.http.Cookie;
}

sub vcl_deliver {
  if (resp.http.X-Zielgruppe) {
    set req.http.X-Zielgruppe = resp.http.X-Zielgruppe;
    set req.http.Set-Cookie = "zielgruppe=" + resp.http.X-Zielgruppe + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/;";

    return (restart);
  }

  if (req.http.Set-Cookie) {
    set resp.http.Set-Cookie = req.http.Set-Cookie;
  }
}

Es handelt sich hier nicht um viel Code, allerdings ist es trotzdem nicht einfach zu verstehen. Nehmen wir jetzt der Einfachheit halber mal an, dass der Benutzer, der die Seite aufruft, zum ersten Mal auf der Webseite landet. Das bedeutet, dass auch noch kein zielgruppe-Cookie gesetzt sein kann und man im zweiten if (elseif (req.restarts == 0)) landet. Um die Zielgruppe zu bestimmen, wird die Anfrage auf /zielgruppe.php umgelenkt und – wie vorher beschrieben – der X-Original-URL-Header gesetzt. Bevor es weitergeht, wird mit unset der Cookieheader gelöscht. Das Skript zielgruppe.php identifiziert anhand des ursprünglichen URL die Zielgruppe und liefert sie über einen HTTP-Header zurück.

In der vcl_deliver-Funktion wird überprüft, ob dieser Header gesetzt ist. Falls ja, ist klar, dass es sich um das Skript zielgruppe.php handelt. Anstatt dass die Antwort zurückgeliefert wird, wird der X-Zielgruppe-Header auf den Request gesetzt, der URL zurückgesetzt und restart zurückgeliefert. Das ist für Varnish das Zeichen, nochmal von vorne bei der vcl_recv-Funktion anzufangen. Varnish hat auch den restarts-Zähler erhöht, weshalb diesmal der letzte Zweig (elseif (req.restarts > 0)) ausgeführt wird. Hier wird der ursprüngliche URL zurückgesetzt. Die anschließende Antwort wird keinen X-Zielgruppe-Header mehr haben. Aufgrund dessen wird im vcl_deliver kein restart mehr ausgeführt. Dafür wird für den Fall, dass vor dem restart ein Set-Cookie-Header zwischengespeichert wurde, dieser auf die neue Antwort gesetzt, womit sich der Browser automatisch an die Zielgruppe erinnert und diesen Cookie beim nächsten Request mitschickt. Das bedeutet auch, dass bei der nächsten Anfrage bereits das erste if in der vcl_recv-Funktion greift, der Zielgruppenheader direkt vom Cookie aus ohne weitere Anfrage gesetzt wird und die Antwort danach pfeilschnell und direkt aus dem Cache ausgeliefert werden kann, sofern die Seite bereits zuvor mit der gleichen Zielgruppe aufgerufen wurde.

Um möglichst oft auf den Cache zuzugreifen, sollte man schauen, dass nur Seiten mehrfach gecacht werden, bei denen das auch Sinn ergibt. Genau hier kommt der Vary-Header ins Spiel. Nur wenn dieser Header auf X-Zielgruppe gesetzt wird, wird ein eigener Cacheeintrag pro Zielgruppe für diese Seite angelegt. Das geschieht ganz einfach mit dem header-Befehl von PHP. Wenn man also die index.php-Seite pro Zielgruppe cachen will, weil der X-Zielgruppe-Header sie beim Ausspielen von Inhalten berücksichtigt hat, könnte das ungefähr wie in Listing 8 ausschauen.

<?php
header('Cache-Control: public, max-age=0, s-maxage=10');
header('X-Reverse-Proxy-TTL: 30');
header('Vary: X-Zielgruppe');

sleep(1);
echo 'War das anstrengend... Aber hier ist die Startseite für ' .  cfirst($_SERVER['HTTP_X_ZIELGRUPPE']);

Mit diesem Set-up ist es aber leider nicht möglich, die Zielgruppe dynamisch zu wechseln. Das bedeutet, dass der Cookie gelöscht werden muss, damit der Benutzer einer neuen Zielgruppe zugeteilt wird. Es ist aber z.B. durchaus möglich, nach dem Laden der Seite einen Ajax Request abzusetzen, der die Zielgrupp neu bestimmt und den bestehenden Cookie überschreibt. Dann sollte man allerdings in der VCL noch die Cache-Control-Header auf 0 setzen, da sonst trotz der gewechselten Zielgruppe noch alte Inhalte aus dem Browsercache geliefert werden könnten.

Abschließend lässt sich sagen, dass sich mit den in diesem Artikel beschriebenen Technologien sehr viele Inhalte cachen lassen, bei denen man es nicht auf den ersten Blick vermutet. Trotzdem muss man schauen, dass man die sogenannten Cache-Hits, also die Zugriffe auf den Cache, möglichst optimiert. Das gelingt, wenn man den Vary-Header sehr sparsam einsetzt und nur, wenn es wirklich sinnvoll ist.

PHP Magazin

Entwickler MagazinDieser Artikel ist im PHP Magazin erschienen. Das PHP Magazin deckt ein breites Spektrum an Themen ab, die für die erfolgreiche Webentwicklung unerlässlich sind.

Natürlich können Sie das PHP Magazin über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. In unserem Shop ist das Entwickler Magazin ferner im Abonnement oder als Einzelheft erhältlich.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

1 Kommentar auf "Varnish und der Vary Header: Dynamische Inhalte effizient cachen"

avatar
400
  Subscribe  
Benachrichtige mich zu:
Matthias
Gast

Der C-Code ist nicht nötig, man kann eine TTL auch in VCL dynamisch zuweisen, siehe https://varnish-cache.org/docs/trunk/reference/vmod_std.html#vmod-std-duration => set beresp.ttl = std.duration(„1w“, 3600s);

X
- Gib Deinen Standort ein -
- or -