Kapitel 4. Massiv skalierbares Content Caching

Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com

4.0 Einleitung

Caching beschleunigt die Bereitstellung von Inhalten, indem es die Antworten speichert, um sie in Zukunft erneut bereitzustellen. Durch die Bereitstellung aus dem Cache entlastet NGINX die vorgelagerten Server, indem es ihnen teure, sich wiederholende Aufgaben abnimmt. Caching erhöht die Leistung und reduziert die Last, sodass du mit weniger Ressourcen schneller bedienen kannst. Caching reduziert außerdem die Zeit und Bandbreite, die für die Bereitstellung von Ressourcen benötigt wird.

Die Skalierung und Verteilung von Caching-Servern an strategischen Standorten kann einen dramatischen Einfluss auf die Nutzererfahrung haben. Für die beste Leistung ist es optimal, die Inhalte in der Nähe des Nutzers zu hosten . Du kannst deine Inhalte auch in der Nähe deiner Nutzer/innen zwischenspeichern. Das ist das Muster der Content Delivery Networks, oder CDNs. Mit NGINX kannst du deine Inhalte überall dort zwischenspeichern, wo du einen NGINX-Server platzieren kannst, so dass du dein eigenes CDN erstellen kannst. Mit dem NGINX-Caching kannst du auch passiv cachen und im Falle eines Upstream-Ausfalls zwischengespeicherte Antworten ausliefern. Die Caching-Funktionen sind nur im Kontext von http verfügbar. Dieses Kapitel behandelt die Caching- und Content-Delivery-Funktionen von NGINX.

4.1 Caching-Zonen

Problem

Du musst Inhalte zwischenspeichern und festlegen, wo der Cache gespeichert wird.

Lösung

Verwende die proxy_cache_path Direktive, um Shared-Memory-Cache-Zonen und einen Speicherort für den Inhalt zu definieren:

proxy_cache_path /var/nginx/cache 
                 keys_zone=main_content:60m 
                 levels=1:2 
                 inactive=3h 
                 max_size=20g
                 min_free=500m;
proxy_cache CACHE;

Das Beispiel für die Cache-Definition erstellt ein Verzeichnis für zwischengespeicherte Antworten im Dateisystem unter /var/nginx/cache und einen gemeinsamen Speicherbereich namens main_content mit 60 MB Speicherplatz. In diesem Beispiel werden die Ebenen der Verzeichnisstruktur festgelegt, das Auslagern von zwischengespeicherten Antworten definiert, nachdem sie drei Stunden lang nicht angefordert wurden, und eine maximale Größe des Caches von 20 GB definiert. Der Parameter min_free weist NGINX an, wie viel Speicherplatz auf der max_size freigehalten werden soll, bevor die gecachten Ressourcen entfernt werden. Die Direktive proxy_cache weist einen bestimmten Kontext an, die Cache-Zone zu nutzen. Die Direktive proxy_cache_path gilt für den Kontext http und die Direktive proxy_cache gilt für die Kontexte http, server und location.

Diskussion

Um das Caching in NGINX zu konfigurieren, musst du einen Pfad und eine Zone angeben, die verwendet werden sollen. Eine Cache-Zone in NGINX wird mit der Direktive proxy_cache_path erstellt. Die Direktive proxy_cache_path legt einen Speicherort für die zwischengespeicherten Informationen und einen gemeinsamen Speicherbereich für aktive Schlüssel und Antwortmetadaten fest. Optionale Parameter für diese Direktive bieten mehr Kontrolle darüber, wie der Cache verwaltet und auf ihn zugegriffen wird.

Der Parameter levels legt fest, wie die Verzeichnisstruktur erstellt wird. Der Wert ist eine durch Doppelpunkte getrennte Liste von Zahlen, die die Länge der aufeinander folgenden Unterverzeichnisnamen festlegt. Tiefere Strukturen helfen zu vermeiden, dass zu viele gecachte Dateien in einem einzigen Verzeichnis auftauchen. NGINX speichert dann das Ergebnis in der angegebenen Dateistruktur, wobei der Cache-Schlüssel als Dateipfad verwendet wird und die Verzeichnisse anhand des Wertes levels aufgeteilt werden.

Mit dem Parameter inactive kannst du festlegen, wie lange ein Cache-Element nach seiner letzten Nutzung gespeichert werden soll. Auch die Größe des Caches kann mit dem Parameter max_size eingestellt werden. Andere Parameter beziehen sich auf den Cache-Ladevorgang, bei dem die Cache-Schlüssel aus den auf der Festplatte zwischengespeicherten Dateien in die gemeinsame Speicherzone geladen werden, sowie auf viele andere Optionen. Weitere Informationen über die Direktive proxy_cache_path findest du in der Dokumentation im Abschnitt "Siehe auch" .

4.2 Hash-Schlüssel zwischenspeichern

Problem

Du musst kontrollieren, wie deine Inhalte zwischengespeichert und abgerufen werden.

Lösung

Verwende die proxy_cache_key Direktive zusammen mit Variablen, um zu definieren, was ein Cache-Treffer oder -Miss ist:

proxy_cache_key "$host$request_uri $cookie_user";

Dieser Cache-Hash-Schlüssel weist NGINX an, Seiten auf der Grundlage des Hosts und der angeforderten URI sowie eines Cookies, das den Benutzer definiert, zwischenzuspeichern. So kannst du dynamische Seiten zwischenspeichern, ohne dass Inhalte angezeigt werden, die für einen anderen Nutzer erstellt wurden.

Diskussion

Der Standardwert proxy_cache_key, der für die meisten Anwendungsfälle geeignet ist, lautet "$scheme$proxy_​host$request_uri". Zu den verwendeten Variablen gehören das Schema (http oder https), proxy_host, wohin die Anfrage gesendet wird, und die Anfrage-URI. Alles zusammen ergibt die URL, an die NGINX die Anfrage weiterleitet. Möglicherweise gibt es noch viele andere Faktoren, die eine eindeutige Anfrage pro Anwendung definieren, z. B. Anfrageargumente, Header, Sitzungskennungen usw., für die du einen eigenen Hash-Schlüssel erstellen möchtest.1

Die Auswahl eines guten Hash-Schlüssels ist sehr wichtig und sollte mit Blick auf die Anwendung gut durchdacht sein. Die Auswahl eines Cache-Schlüssels für statische Inhalte ist in der Regel recht einfach; die Verwendung des Hostnamens und der URI ist ausreichend. Die Auswahl eines Cache-Schlüssels für relativ dynamische Inhalte, wie z. B. Seiten für eine Dashboard-Anwendung, erfordert mehr Wissen darüber, wie die Nutzer mit der Anwendung interagieren und wie unterschiedlich die Erfahrungen der Nutzer sind. Bei der Zwischenspeicherung dynamischer Inhalte ist die Verwendung von Sitzungskennungen wie Cookies oder JWT-Tokens besonders nützlich. Aus Sicherheitsgründen möchtest du vielleicht nicht, dass zwischengespeicherte Daten von einem Nutzer zu einem anderen weitergegeben werden, ohne den Kontext vollständig zu verstehen. Die Direktive proxy_cache_key konfiguriert die zu hashende Zeichenkette für den Cache-Schlüssel. Die Direktive proxy_cache_key kann im Kontext der Blöcke http, server und location gesetzt werden und bietet so eine flexible Kontrolle darüber, wie Anfragen gecached werden.

4.3 Cache-Sperren

Problem

Du möchtest kontrollieren, wie NGINX gleichzeitige Anfragen für eine Ressource behandelt, für die der Cache aktualisiert wird.

Lösung

Mit der Direktive proxy_cache_lock kannst du sicherstellen, dass immer nur eine Anfrage in den Cache geschrieben werden kann, während nachfolgende Anfragen darauf warten, dass die Antwort in den Cache geschrieben und von dort serviert wird:

proxy_cache_lock on;
proxy_cache_lock_age 10s;
proxy_cache_lock_timeout 3s;

Diskussion

Wir wollen keine Anfragen weiterleiten, bei denen frühere Anfragen für denselben Inhalt noch im Umlauf sind und gerade in den Cache geschrieben werden. Die Direktive proxy_cache_lock weist NGINX an, Anfragen zurückzuhalten, die für eine Ressource im Cache bestimmt sind, die gerade aufgefüllt wird. Die Proxy-Anfrage, die den Cache auffüllt, hat nur eine begrenzte Zeitspanne, bevor eine andere Anfrage versucht, die Ressource aufzufüllen. Dies wird durch die Direktive proxy_cache_lock_age festgelegt, die standardmäßig fünf Sekunden beträgt. NGINX kann auch zulassen, dass Anfragen, die eine bestimmte Zeit gewartet haben, an den Proxy-Server weitergeleitet werden, der dann nicht versucht, den Cache zu füllen. Dies wird mit der Direktive proxy_cache_lock_timeout festgelegt, die ebenfalls auf fünf Sekunden eingestellt ist. Du kannst dir proxy_cache_lock_age und proxy_cache_lock_timeout wie folgt vorstellen: "Du brauchst zu lange, ich fülle den Cache für dich auf" bzw. "Du brauchst zu lange, um zu warten, ich hole mir, was ich brauche und lasse dich den Cache in deiner eigenen Zeit auffüllen".

4.4 Stale Cache verwenden

Problem

Du möchtest abgelaufene Cache-Einträge senden, wenn der Upstream-Server nicht erreichbar ist.

Lösung

Verwende die Direktive proxy_cache_use_stale mit einem Parameterwert, der festlegt, für welche Fälle NGINX den Stale-Cache verwenden soll:

proxy_cache_use_stale error timeout invalid_header updating 
  http_500 http_502 http_503 http_504
  http_403 http_404 http_429;

Diskussion

Die Fähigkeit von NGINX, veraltete Cache-Ressourcen auszuliefern, während deine Anwendung nicht korrekt zurückkehrt, kann wirklich den Tag retten. Diese Funktion kann dem Endnutzer die Illusion eines funktionierenden Webdienstes vermitteln, während das Backend möglicherweise nicht erreichbar ist. Die Bereitstellung aus dem Stale-Cache verringert außerdem die Belastung deiner Backend-Server, wenn es zu Problemen kommt, was wiederum dem Entwicklungsteam etwas Spielraum zur Fehlerbehebung verschafft.

Die Konfiguration weist NGINX an, veraltete Cache-Ressourcen zu verwenden, wenn die Upstream-Anfrage eine Zeitüberschreitung aufweist, einen invalid_header -Fehler liefert oder Antwortcodes der Stufen 400 und 500 zurückgibt. Die Parameter error und updating sind ein wenig speziell. Der Parameter error erlaubt die Verwendung des Stale-Cache, wenn kein Upstream-Server ausgewählt werden kann. Mit dem Parameter updating wird NGINX angewiesen, veraltete Cache-Ressourcen zu verwenden, während der Cache mit neuen Inhalten aktualisiert wird.

4.5 Cache-Umgehung

Problem

Du brauchst die Möglichkeit, das Caching zu umgehen.

Lösung

Verwende die Direktive proxy_cache_bypass mit einem Wert, der nicht leer oder ungleich Null ist. Eine Möglichkeit, dies dynamisch zu tun, besteht darin, eine Variable in einem location Block, der nicht gecacht werden soll, auf einen anderen Wert als einen leeren String oder 0 zu setzen:

proxy_cache_bypass $http_cache_bypass;

Die Konfiguration weist NGINX an, den Cache zu umgehen, wenn der HTTP-Request-Header namens cache_bypass auf einen Wert ungleich 0 gesetzt wird. In diesem Beispiel wird ein Header als Variable verwendet, um zu bestimmen, ob das Caching umgangen werden soll - der Kunde muss diesen Header für seine Anfrage selbst setzen.

Diskussion

Es gibt eine Reihe von Szenarien, die erfordern, dass die Anfrage nicht im Cache gespeichert wird. Hierfür stellt NGINX die Direktive proxy_cache_bypass zur Verfügung. Wenn der Wert nicht leer oder ungleich Null ist, wird die Anfrage an einen vorgelagerten Server gesendet und nicht aus dem Cache gezogen. Die verschiedenen Anforderungen und Szenarien für die Umgehung des Caches hängen vom Anwendungsfall deiner Anwendung ab. Die Techniken zur Umgehung des Caches können so einfach sein wie die Verwendung eines Request- oder Response-Headers oder so kompliziert wie das Zusammenspiel mehrerer map Blöcke.

Es gibt viele Gründe, warum du den Cache umgehen möchtest, z. B. bei der Fehlersuche oder beim Debuggen. Es kann schwierig sein, Probleme zu reproduzieren, wenn du ständig Seiten aus dem Cache abrufst oder wenn dein Cache-Schlüssel an eine bestimmte Benutzerkennung gebunden ist. Die Möglichkeit, den Cache zu umgehen, ist wichtig. Zu den Optionen gehört unter anderem, den Cache zu umgehen, wenn ein bestimmtes Cookie, ein Header oder ein Anfrageargument gesetzt ist. Du kannst den Cache für einen bestimmten Kontext, z. B. einen location Block, auch komplett ausschalten, indem du proxy_cache off; setzt.

4.6 Cache-Löschung mit NGINX Plus

Problem

Du musst ein Objekt aus dem Cache ungültig machen.

Lösung

Verwende die Funktion purge von NGINX Plus, die Direktive proxy_cache_purge und eine nicht leere oder nullwertige Variable:

map $request_method $purge_method {
  PURGE 1;
  default 0;
}
server {
  # ...
  location / {
    # ...
    proxy_cache_purge $purge_method;
  }
}

In diesem Beispiel wird der Cache für ein bestimmtes Objekt geleert, wenn es mit der Methode PURGE angefordert wird. Das folgende curl Beispiel zeigt, wie der Cache einer Datei namens main.js geleert wird:

$ curl -X PURGE http://www.example.com/main.js

Diskussion

Eine gängige Methode, um statische Dateien zu verwalten, ist es, einen Hash der Datei in den Dateinamen aufzunehmen. Dadurch wird sichergestellt, dass dein CDN neue Inhalte und Codes als neue Dateien erkennt, weil sich der URI geändert hat. Bei dynamischen Inhalten, für die du Cache-Schlüssel festgelegt hast, die nicht zu diesem Modell passen, funktioniert das jedoch nicht. In jedem Caching-Szenario musst du eine Möglichkeit haben, den Cache zu löschen.

NGINX Plus bietet eine einfache Methode zum Löschen von gecachten Antworten. Die Direktive proxy_cache_purge bereinigt die gecachten Einträge, die der Anfrage entsprechen, wenn der Wert Null oder ein nicht leerer Wert übergeben wird. Eine einfache Möglichkeit, die Bereinigung einzurichten, ist das Mapping der Anfragemethode für PURGE. Du solltest dies jedoch in Verbindung mit dem Modul geoip oder einer einfachen Authentifizierung verwenden, um sicherzustellen, dass nicht jeder deine wertvollen Cache-Elemente bereinigen kann. NGINX hat auch die Verwendung von * ermöglicht, das Cache-Elemente löscht, die mit einem gemeinsamen URI-Präfix übereinstimmen. Um Wildcards zu verwenden, musst du deine Direktive proxy_cache_path mit dem Argument purger=on konfigurieren.

4.7 Cache Slicing

Problem

Du musst die Effizienz des Caching erhöhen, indem du die Ressource in Fragmente aufteilst.

Lösung

Verwende die NGINX slice Direktive und ihre eingebetteten Variablen, um das Cache-Ergebnis in Fragmente zu unterteilen:

proxy_cache_path /tmp/mycache keys_zone=mycache:10m;
server {
  # ...
  proxy_cache mycache;
  slice 1m;
  proxy_cache_key $host$uri$is_args$args$slice_range;
  proxy_set_header Range $slice_range;
  proxy_http_version 1.1;
  proxy_cache_valid  200 206 1h;
 
  location / {
    proxy_pass http://origin:80;
  }
}

Diskussion

Diese Konfiguration definiert eine Cache-Zone und aktiviert sie für den Server. Mit der Direktive slice wird NGINX dann angewiesen, die Antwort in 1 MB große Dateisegmente zu zerlegen . Die zwischengespeicherten Ressourcen werden gemäß der Direktive proxy_cache_key gespeichert. Beachte die eingebettete Variable mit dem Namen slice_range. Dieselbe Variable wird als Header bei der Anfrage an den Ursprung verwendet, und die HTTP-Version der Anfrage wird auf HTTP/1.1 hochgestuft, da 1.0 keine Byte-Range-Anfragen unterstützt. Die Cache-Gültigkeit wird für Antwortcodes von 200 oder 206 für eine Stunde festgelegt, und dann werden der Standort und der Ursprung definiert.

Das Cache-Slice-Modul wurde für die Auslieferung von HTML5-Videos entwickelt, die Byte-Range-Anfragen verwenden, um Inhalte als Pseudostream an den Browser zu senden. Standardmäßig ist NGINX in der Lage, Byte-Range-Anfragen aus seinem Cache zu bedienen. Wenn eine Anfrage für einen Bytebereich für nicht gecachte Inhalte gestellt wird, fordert NGINX die gesamte Datei vom Ursprung an. Wenn du das Cache-Slice-Modul verwendest, fordert NGINX nur die erforderlichen Segmente vom Ursprung an. Bereichsanfragen, die größer als die Slice-Größe sind und die gesamte Datei umfassen, lösen Unteranfragen für jedes der benötigten Segmente aus, die dann zwischengespeichert werden. Wenn alle Segmente im Cache sind, wird die Antwort zusammengestellt und an den Client gesendet. So kann NGINX Inhalte, die in Bereichen angefordert werden, effizienter im Cache speichern und bereitstellen.

Das Cache-Slice-Modul sollte nur für große Ressourcen verwendet werden, die sich nicht ändern. NGINX validiert den ETag jedes Mal, wenn es ein Segment vom Ursprung erhält. Wenn sich der ETag auf der Ursprungsseite ändert, bricht NGINX die Cache-Population des Segments ab, da der Cache nicht mehr gültig ist. Wenn sich der Inhalt ändert und die Datei kleiner ist oder dein Ursprung mit Lastspitzen während des Cache-Füllvorgangs umgehen kann, ist es besser, die in Rezept 4.3 beschriebene Direktive cache_lock zu verwenden. Mehr über Cache-Slicing-Techniken erfährst du in dem Blog, der im Abschnitt "Siehe auch" aufgeführt ist .

1 Jede beliebige Kombination von Text oder Variablen, die NGINX zur Verfügung stehen, kann als Cache-Schlüssel verwendet werden. Eine Liste der Variablen ist in NGINX verfügbar.

Get NGINX Kochbuch, 3. Auflage now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.