Der Proxy Cache – Wieso? Weshalb? Warum?

Man hat Änderungen (HTML, CSS, JavaScript, Bilder,…) an einer Webseite durchgeführt und der Kunde kann diese, trotz geleertem Browser-Cache, an seinem Arbeitsplatz nicht sehen? Gerade bei größeren Firmen kann dies am Einsatz eines Proxies liegen.
In diesem Post möchte ich kurz auf den Grund für den Einsatz eines solchen Proxies sowie den möglichen Umgang als Web-Entwickler mit diesem eingehen.

Das meiste in desem Artikel trifft auch auf den generellen Umgang mit Caches zu und findet so auch Verwendung im Bereich der Performance-Optimierung für High Traffic Webseiten.

Wieso ein Proxy und was sind die Folgen?

Neben zahlreichen anderen Funktionen (Anonymisierung, Filterrung, Schutz,…) wird ein Proxy in Netzwerken mit vielen Clients oft dazu eingesetzt die Netzauslastung zu reduzieren. Dazu wird z.B. bei Anfragen aus dem lokalen Netzwerk an externe Quellen das Ergebnis gespeichert. Bei der nächsten Anfrage eines Clients an die externe Quelle verlässt der Request dann nicht mehr das lokale Netzwerk sondern der Proxy liefert das vorher gespeicherte Ergebnis zurück. Der Proxy stellt also stellvertretend für die ihm zugeordneten Clients die Anfrage an den eigentlichen Server.

Die Konsequenz für uns Web-Entwickler ist naheliegend: Hat der Proxy eine Ressource erstmal zwischengespeichert können wir soviel an ihr ändern wie wir wollen, der Kunde bekommt weiterhin die Version des Proxies ausgeliefert. Damit trotzdem eine gewisse Aktualität gewährleistet wird sorgt der Proxy dafür, dass nach einer gewissen Zeit die Ressource verfällt und der Inhalt bei der nächsten Anfrage erneut von der externen Quelle geladen wird. Dieses Intervall kann jedoch unterschiedlich groß sein und möchte man eine Änderung unmittelbar für den Kunden bereit stellen kommt das Abwarten ggf. nicht in Frage.  Was also tun?

HTTP-Header Cache-Control

Das HTTP-Protokoll bringt, ab Version 1.1, für diese Thematik einen entsprechendes Header names „Cache-Control“ mit. Über diese Header ist es möglich explizit Einfluss auf den Proxy Cache zu nehmen. So macht es manchmal Sinn das Caching für einen Test- oder Staging-Server komplett via HTTP-Antwort zu deaktivieren oder das Aktualisierungsintervall entsprechend kurz zu konfigurieren.
Die wichtigsten Parameter für den Header lauten:

  • no-store: Verbietet jegliches Zwischenspeichern der Ressource
  • no-cache: Sorgt dafür das jeder Request an den Cache zur Prüfung an den Zielserver geht bevor eine zwischengespeicherte Ressource ausgeliefert wird
  • public/private: Unterscheidet zwischen dem privaten (Browser) und dem öffentlichen (Proxy) Cache. Die meisten Header kann man auch zur Kontrolle des Browser-Caches verwenden.
  • max-age=123: Zeit (in Sekunden) die ein Element gültig bleibt

Die Header können auf die üblichen Arten gesetzt werden, zum Beispiel:

PHP:

[php]header("Cache-Control: no store" );[/php]

Apache mod-headers:

[code]Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"[/code]

HTML Meta Tags:

HTML bietet die Möglichkeit Meta Tags, ähnlich den HTTP Headern,  zur Steuerung des Caches anzugeben. Da Proxy-Server normalerweise gar nicht die HTML-Daten inspizieren haben die Tags in diesem Zusammenhang in der Regel keinen Effekt. Das Ganze sähe dann z.B. so aus:

[code lang=“html“]<meta http-equiv="cache-control" content="no-cache">[/code]

Expires

Dieses Feld gibt es auch als Meta-Tag und im HTTP-Header und definiert den Zeitpunkt bis wann die Ressource gültig ist. Gibt man hier ein Datum in der Vergangenheit an erreicht man dasselbe wie mit no-cache.
Grundsätzlich lässt sich damit die Gültigkeit der Daten genauer steuern als mit dem Cache-Control Header.

ETag

Ebenfalls mit HTTP 1.1 eingeführt wurde der Entity-Tag. Dieses Feld ist eine beliebige Zeichenkette die eine Version der jeweiligen Ressource definiert. Der Cache speichert sich den ETag bei der ersten Anfrage ab. Bei einer erneuten Anfrage wird dann das Feld If-None-Match mit dem entsprechenden String im Header mitgesendet. Darauf prüft der Server ob der ETag sich geändert hat und sollte dies nicht der Fall sein kann er mit dem Status 304 Not Modified antworten.

Interessant ist dies besonders durch die Unterstützung diverser Webserver wie Apache und lighttpd. Dies ermöglicht eine automatische Aktualisierung des ETags basierend auf Änderungen am Dateisystem.

Request-URL ändern

Da das Caching eines Proxies in der Regel nicht auf den Inhalt einer Ressource sondern auf deren URL basiert, reicht es oft die URL geringfügig anzupassen.
So reicht es z.B. die CSS, Bild- oder JavaScript-Datei mit einem, nicht verwendeten, GET-Parameter zu versehen:

[code]http://www.example.com/style.css?v=1[/code]

Hat man sowieso eine Versionierung für seine JavaScript-/CSS-Dateien, umso besser.

Sonstiges

SSL
Bei einer SSL-Verbindung kann der Proxy-Cache natürlich nicht eingreifen

STRG+F5
In einigen Browsern (z.B. Firefox) erreicht man so, dass der Browser die HTTP Anfrage um die folgenden Header erweitert:

[code]
Pragma: no-cache
Cache-Control: no-cache
[/code]

Damit soll die Gegenseite aufgefordert werden den Cache nicht zu verwenden. Proxies ignorieren dies aber in der Regel da das Cache Verhalten nicht von den Clients beeinflusst werden soll. Hinzu kommt der Pragma Header auch nur bedingt berücksichtigt wird.

Reverse Proxy

Ein Proxy kann nicht nur als Stellvertreter für Clients sondern auch für einen oder mehrere Server eingesetzt werden. Dies wird oft bei Hochlast-Webseiten zur Lastverteilung eingesetzt. Ein Beispiel dafür ist varnish.

Fazit

Es gibt einige, gut funktionierende Möglichkeiten den (Proxy-) Cache von vornherein zu steuern. Je nach Einsatzfeld sollte man sich jedoch genau überlegen welche Technik man wie einsetzt, da man sich sonst die eigentlichen Vorteile von Caching (Lastveringerung, geringere Latenz,…) verbaut. Für einen Testserver mag z.B. ein no-cache, no-store Header sinnvoll sein, im Livebetrieb sollte man allerdings etwas diffiziler vorgehen und vielleicht auf ETag setzen.

Sind die Ressourcen allerdings bereits ohne entsprechend gesetzte Header im Cache gelandet hilft eigentlich nur warten oder das ändern der URL.

Weiterführende Links:

Danke auch an Daniel für den reichlichen Input zu diesem Thema.


Leave a Reply

Your email address will not be published.