Zurück zum Blog

Nginx HTTP-Proxying, Load Balancing, Pufferung und Caching: Eine Übersicht

Nginx HTTP-Proxying, Load Balancing, Pufferung und Caching: Eine Übersicht
Einführung

Nginx ist ein leistungsstarker Webserver, der auch als Reverse-Proxy, Mail-Proxy, Load-Balancer und HTTP-Cache verwendet wird. Nginx ist kostenlos und Open-Source, sodass jeder es herunterladen und in seiner Serverumgebung verwenden kann.

Vielleicht haben Sie Nginx bereits zur Bereitstellung von Websites verwendet. In diesem Tutorial werden wir die anderen Funktionen von Nginx besprechen. Die HTTP-Proxying-Funktion von Nginx ermöglicht es, Anfragen zur Verarbeitung an Backend-HTTP-Server weiterzuleiten. Mit dieser Funktion können Sie mehrere Backend-Server einrichten. Sie ermöglicht es Ihnen, Ihre Infrastruktur nach Bedarf zu skalieren, um Spitzen bei Client-Anfragen zu bewältigen.

Im weiteren Verlauf des Tutorials werden Sie lernen, wie Sie Ihre Infrastruktur mithilfe der Nginx-Load-Balancing-Eigenschaften, der Pufferung und des Cachings von Antworten zu skalieren, um Ihre Serverleistung zu verbessern und eine bessere Benutzererfahrung für Clients zu gewährleisten. Lassen Sie uns beginnen!

Das Wichtigste zuerst: Um mit Nginx zu beginnen, werfen Sie einen Blick auf unser Tutorial zur Installation von Nginx auf Ihrem Ubuntu-Server.

Allgemeine Informationen zum Proxying

Wenn sich Ihr Wissen über Webserver nur auf die Verarbeitung von Website-Anfragen und die Bereitstellung von Webseiten beschränkt, fragen Sie sich vielleicht, warum wir Anfragen über einen Proxy leiten müssen. Im Folgenden werden wir die Gründe dafür erläutern.

Ein Grund, Anfragen von Nginx an andere Server weiterzuleiten, ist die Unterstützung der Skalierbarkeit Ihrer Infrastruktur. Nginx verarbeitet standardmäßig viele Verbindungen gleichzeitig. Dies macht es perfekt als ersten Kontaktpunkt für Clients. Anschließend kann es die Anfragen an verschiedene Backend-Server weiterleiten, um die eigentliche Verarbeitung der Client-Anfragen zu übernehmen. Dadurch wird die Last verteilt. Auf diese Weise wird sichergestellt, dass Sie Ihre Infrastruktur so weit wie möglich skalieren können. Es ermöglicht Ihnen auch, andere Server für Wartungsarbeiten herunterzufahren, während andere weiterhin Anfragen bedienen.

Der zweite Grund, warum Sie Anfragen an andere Server weiterleiten möchten, ist, wenn Sie Anwendungsserver verwenden, die nicht dafür geeignet sind, Anfragen direkt von Clients in Live-Produktionsumgebungen zu verarbeiten. Mehrere Frameworks, einschließlich Webserver, sind nicht für eine so hohe Leistung wie Nginx ausgelegt. Wenn Sie Nginx als Einstiegspunkt festlegen und Anfragen an diese leistungsschwächeren Server weiterleiten, können Sie Ihren Benutzern eine bessere Erfahrung bieten. Darüber hinaus kann dies eine erhöhte Sicherheit für Ihre Anwendung garantieren.

Der Prozess des Proxyings von Anfragen in Nginx beinhaltet das Manipulieren einer Anfrage vom Nginx-Server und das Weiterleiten an andere Backend-Server für die eigentliche Verarbeitung. Sobald die anderen Backend-Server die Anfrage verarbeitet haben, leiten sie das Ergebnis an Nginx zurück. Dieses sendet das Ergebnis dann als Antwort an den Client. Der Client ist in diesem Fall ein Webbrowser oder sogar eine mobile Web-App. Die anderen Backend-Server können lokale Server sein, die im Internet nicht öffentlich zugänglich sind, Remote-Server oder sogar andere virtuelle Server innerhalb der Server-Block-Konfigurationen von Nginx. Diese anderen Server, an die Nginx Anfragen weiterleitet, werden als Upstream-Server bezeichnet..

Nginx kann Anfragen an Server weiterleiten, die über verschiedene Protokolle kommunizieren, darunter HTTP(S), Memcached, SCGI, FastCGI, und uWSGI. Für jeden Protokolltyp gibt es eine Reihe von Direktiven. Unser Fokus für dieses Tutorial liegt auf dem HTTP-Protokoll. Nginx analysiert die Anfragen und Nachrichtenkomponenten in ein Format, das der Upstream-Server interpretieren und verarbeiten kann.

Analysieren eines einfachen HTTP-Proxy-Passes

Die einfachste Art von Proxy beinhaltet das Weiterleiten einer Anfrage an einen einzelnen Server, der über HTTP kommuniziert. Diese Art von Proxy wird im Allgemeinen als „Proxy Pass“ bezeichnet und von der treffend benannten Direktive proxy_pass in den Nginx-Konfigurationsdateien verarbeitet.

Die Direktive proxy_pass wird innerhalb von location-Blöcken verwendet. Sie befindet sich auch in Blöcken eines location-Kontexts und in limit_except-Kontexten. Wenn eine Anfrage mit einem Speicherort übereinstimmt, der eine proxy_pass-Direktive enthält, geht die Anfrage an die URL, die die Direktive angibt. Unten finden Sie ein Beispiel für ein Konfigurations-Snippet:

proxy_pass_conf

Im obigen Beispiel würden die Anfragen an Port 80 an localhost:3000 gesendet:

nginx default page

Der obige Screenshot zeigt die Standard-Nginx-Seite, wenn Sie versuchen, localhost zu erreichen. Nach dem Neustart des Nginx-Servers mit aktivierter proxy_pass-Direktive werden alle Anfragen an Port 3000 weitergeleitet. Auf Port 3000 läuft eine Demo-Anwendung, die Sie im folgenden Bild sehen können und die Sie direkt von localhost aus erreichen können, ohne den Port anzugeben:

localhost after applying proy pass

Im nächsten Beispiel wurde am Ende des Servers in der proxy_pass-Definition kein URI angegeben. Bei Definitionen, die diesem Muster entsprechen, wird der vom Client angeforderte URI unverändert an den Upstream-Server übergeben.

Wenn dieser Block beispielsweise eine Anfrage für /match/url/here verarbeitet, wird der Anfrage-URI als http://example.com/match/url/here an den Server example.com weitergeleitet.

Unten finden Sie ein Beispiel für ein alternatives Konfigurations-Snippet:

Wie Sie im obigen Snippet sehen können, haben wir am Ende des Proxy-Servers ein URI-Segment als new/url/prefix definiert. Wenn Sie einen URI in der proxy_pass-Definition definieren, wird der Teil der Anfrage, der mit der location-Definition übereinstimmt, durch diesen URI ersetzt, wenn er zur Verarbeitung an den Upstream-Server weitergeleitet wird.

Beispielsweise wird eine Anfrage für /match/url/here auf dem Nginx-Server als http://example.com/new/url/here an den Upstream-Server weitergeleitet. Das /match/url wird durch /new/url ersetzt. Bitte beachten Sie diesen Punkt.

In einigen Fällen ist die Weitergabe von URIs wie oben beschrieben nicht möglich. In solchen Fällen ignoriert Nginx den URI am Ende der proxy_pass-Definition. Letztendlich wird entweder der ursprüngliche URI vom Client oder der von anderen Direktiven geänderte URI an den Upstream-Server übergeben.

Ein Beispiel hierfür ist, wenn reguläre Ausdrücke mit der Location übereinstimmen. Nginx kann möglicherweise nicht bestimmen, welcher Teil des URI mit dem Ausdruck übereinstimmt. Daher sendet es den ursprünglichen Client-Anfrage-URI. Dies führt zum Umschreiben und Verarbeiten des Client-URIs im selben Block. In einem solchen Fall wird der umgeschriebene URI übergeben.

Wie verarbeitet Nginx Header?

Header sind entscheidend dafür, wie ein Server eine Anfrage verarbeitet. Einige Header können Authentifizierungsinformationen enthalten. Daher müssen wir verstehen, wie das Nginx-Proxying die Header verarbeitet. Die Proxy-Anfrage von Nginx an den Upstream-Server sieht anders aus als diejenige, die direkt vom Client kam. Einige der Unterschiede resultieren aus den Headern, die mit der Proxy-Anfrage gesendet werden.

Während des Proxyings einer Anfrage nimmt Nginx Anpassungen an den vom Client empfangenen Anfrage-Headern vor. Einige dieser Anpassungen umfassen:

  • Das Entfernen aller leeren Header. Leere Header blähen die Anfrage nur auf, daher macht es keinen Sinn, sie an den Upstream-Server weiterzuleiten.

  • Alle Header, die Unterstriche enthalten, werden standardmäßig als ungültig betrachtet und daher aus der Anfrage entfernt. Wenn Sie dieses Verhalten ändern und Nginx erlauben möchten, Header mit Unterstrichen als gültig zu interpretieren, können Sie die Direktive underscores_in_headers auf „on“ setzen. Wenn Sie dies nicht tun, erreichen solche Header vom Client niemals den Upstream-Server.

  • Der „Host“-Header wird auf den durch die Variable $proxy_host angegebenen Wert umgeschrieben. Dies ist die IP-Adresse oder der Name und die Portnummer des Upstream-Servers, wie in der proxy_pass-Direktive angegeben.

  • Der Wert des „Connection“-Headers ändert sich in „close“. Der Connection-Header enthält Informationen über eine bestimmte Verbindung, die zwischen zwei Parteien hergestellt wurde. Wenn Nginx seinen Wert auf „close“ setzt, signalisiert dies dem Upstream-Server, dass die Verbindung geschlossen wird, sobald die ursprüngliche Anfrage beantwortet wurde, weshalb er keine dauerhafte Verbindung erwarten sollte.

Hier sind einige Punkte, die wir aus den oben beschriebenen Anpassungen der Proxy-Anfrage-Header festhalten können:

  • Wenn Sie nicht möchten, dass ein Header an den Upstream-Server übergeben wird, wird er durch das Setzen auf eine leere Zeichenkette vollständig aus der Anfrage entfernt.

  • Wenn die Anwendung auf Ihrem Upstream-Server Nicht-Standard-Header verarbeitet, stellen Sie sicher, dass die Header keinen Unterstrich enthalten. Optional können Sie die Direktive underscores_in_headers in Ihrer Konfiguration auf „on“ setzen (gültig entweder im Kontext der Standard-Serverdeklaration für die IP-Adresse/Port-Kombination oder im HTTP-Kontext). Dadurch wird sichergestellt, dass die Header nicht als ungültig markiert und somit tatsächlich an den Upstream-Server übergeben werden.

  • Der „Host“-Header ist in den meisten Proxy-Situationen sehr wichtig. Er ist standardmäßig auf den Wert von $proxy_host gesetzt, eine Variable, die den Domainnamen oder die IP-Adresse und den Port enthält, die aus der proxy_pass-Spezifikation abgerufen wurden. Diese Adresse wird standardmäßig ausgewählt und direkt aus den Verbindungsinformationen bezogen. Es ist die einzige Adresse, bei der Nginx die Garantie hat, dass der Upstream-Server darauf antwortet.

Nachfolgend sind die häufigsten Werte für den „Host“-Header aufgeführt:

  • $host – eine Variable, die in der Reihenfolge der Präferenz auf den Hostnamen aus der Anfragezeile selbst, den „Host“-Header aus der Client-Anfrage oder den mit der Anfrage übereinstimmenden Servernamen gesetzt wird.

  • $http_host – eine Variable, die den „Host“-Header auf den „Host“-Header aus der Client-Anfrage setzt. Die Header in der Anfrage des Clients stehen Nginx immer als Variablen zur Verfügung. Diese Variablen beginnen mit dem Präfix $http_, gefolgt vom Headernamen in Kleinbuchstaben. Während die Variable $http_host meistens gut funktioniert, kann es zu einem Fehlschlagen der Weiterleitung führen, wenn der Client-Anfrage ein gültiger „Host“-Header fehlt.

  • $proxy_host – eine Variable, die den „Host“-Header auf die Kombination aus Domainname oder IP-Adresse und Port setzt, die aus der Spezifikation von proxy_pass abgerufen wurde. Dies ist aus Sicht von Nginx das Standardverhalten und gilt daher als sicher. Es ist jedoch möglicherweise nicht das, was der Server benötigt, um die Anfrage korrekt zu verarbeiten.

Die meisten Konfigurationen beinhalten das Setzen des „Host“-Headers auf die Variable $host. Dies ist äußerst flexibel und liefert dem Upstream-Server präzise ausgefüllte Header.

Setzen und Ändern von Headern

Die Direktive proxy_set_header ermöglicht es uns, Header für Proxy-Verbindungen zu setzen oder zu ändern. Beim zuvor besprochenen „Host“-Header können wir Folgendes tun, um zusätzliche Header zu ändern und hinzuzufügen, die bei Proxy-Anfragen üblich sind:

Im obigen Konfigurationsschnipsel setzen wir den „Host“-Header auf die Variable $host, die Informationen über den ursprünglich angeforderten Host enthält. Wir setzen den Header X-Forwarded-Proto mit Informationen über das Schema der ursprünglichen Anfrage des Clients (dies kann entweder eine HTTP- oder eine HTTPS-Anfrage sein).

Wir übergeben die tatsächliche IP-Adresse des Clients an X-Real-IP. Dies ermöglicht es dem Upstream-Server, angemessene Entscheidungen zu treffen oder Protokolle basierend auf der IP-Herkunft des Clients zu speichern. Der Header X-Forwarded-For enthält eine Liste aller IP-Adressen von Servern, über die der Client weitergeleitet wurde, bevor er diesen Punkt erreicht hat. Im obigen Code-Schnipsel setzen wir ihn auf die Variable $proxy_add_x_forwarded_for. Diese Variable übernimmt den Wert des ursprünglichen, vom Client stammenden X-Forwarded-For-Headers und fügt die IP-Adresse des Nginx-Proxy-Servers am Ende hinzu.

Wenn Sie möchten, dass die proxy_set_header-Direktiven in mehr als einem Location-Block referenziert werden, können Sie diese in den Server- oder HTTP-Kontext auslagern. Betrachten Sie den folgenden Konfigurationsschnipsel:

Definieren eines Upstream-Kontexts zum Lastausgleich von Proxy-Verbindungen

Bis zu diesem Punkt haben Sie ein Verständnis dafür, wie Sie einen einfachen HTTP-Proxy zu einem einzelnen Backend-Upstream-Server einrichten. Glücklicherweise können Sie mit Nginx eine solche Konfiguration skalieren, indem Sie Pools von Backend-Servern definieren, an die die Anfragen zur Bearbeitung weitergeleitet werden.

Nginx bietet eine Direktive namens upstream, mit der ein Pool von Servern definiert wird. Innerhalb der Konfiguration der Direktive dürfen Sie nur Server angeben, die in der Lage sind, die Anfrage eines Clients zu bearbeiten. Nginx als Proxy-Server ermöglicht die Skalierung der Infrastruktur mit minimalem Aufwand. Die upstream-Direktive muss innerhalb des http-Kontexts Ihrer Nginx-Konfiguration angegeben werden.

Hier ist ein Beispiel, das die upstream-Direktive zeigt:

Im obigen Konfigurations-Code-Snippet haben wir einen Upstream-Kontext namens several_backend_hosts definiert. Der definierte Kontextname ist nun innerhalb von Proxy-Passes verfügbar. Er kann verwendet werden, als wäre er eine reguläre Domain, wie im Beispiel gezeigt. Innerhalb des Server-Blocks leiten wir alle Anfragen an example.com/proxy-me/… an den Pool weiter, den wir mit der upstream-Direktive definiert haben, in diesem Fall several_backend_hosts. Ein Host innerhalb des Pools wird ausgewählt, um eingehende Anfragen zu bearbeiten, indem ein konfigurierbarer Algorithmus angewendet wird. Standardmäßig folgt die Auswahl einem Round-Robin (zyklischen) Prozess – jede Anfrage wird nacheinander an einen anderen Host weitergeleitet.

So ändern Sie den Upstream-Balancing-Algorithmus

Wie oben hervorgehoben, folgt der Auswahlprozess einem Round-Robin-Verfahren. In diesem Abschnitt werden wir sehen, wie wir den vom Upstream-Pool verwendeten Balancing-Algorithmus ändern können. Um den Algorithmus zu ändern, fügen Sie andere Direktiven oder Flags innerhalb des Upstream-Kontexts ein, wie unten definiert:

  • (Round-Robin) – Wenn keine andere Upstream-Balancing-Direktive angegeben ist, werden standardmäßig an jeden im Upstream-Kontext definierten Server nacheinander Anfragen weitergeleitet.

  • least_conn – Diese Direktive weist den Upstream an, den Backend-Server mit der geringsten Anzahl aktiver Verbindungen auszuwählen. Dies ist in Situationen anwendbar, in denen Verbindungen zu einem Backend-Server eine Weile bestehen bleiben können.

  • hash – Diese Direktive ist für das Memcached-Proxying üblich. Verbindungen werden basierend auf dem Wert eines zufällig bereitgestellten Hash-Schlüssels an die Backend-Server weitergeleitet. Der Wert des Hash-Schlüssels kann aus Variablen, Text oder einer Kombination aus beiden bestehen. hash ist zufällig die einzige Balancing-Methode, die eine Eingabe von Benutzern erfordert, um als Schlüssel für den Hash zu dienen.

  • ip_hash – Diese Direktive weist den Upstream an, Anfragen basierend auf der IP-Adresse des Clients auf verschiedene Server zu verteilen. Die ersten drei Oktette der IP-Adresse sind der Schlüssel zur Bestimmung, welcher Server eine Anfrage verarbeiten soll. Ein Vorteil dieser Direktive ist, dass Clients in der Regel jedes Mal denselben Server zugewiesen bekommen, was die Sitzungskonsistenz gewährleistet.

Hier ist ein Beispiel dafür, wie wir die Balancing-Algorithmus-Direktive zum Upstream-Kontext hinzufügen können:

Im obigen Snippet wählt Nginx einen der Server mit den wenigsten Verbindungen aus, um eine eingehende Anfrage zu verarbeiten. Die ip_hash-Direktive folgt derselben Syntax. Für die hash-Direktive müssen Sie einen Schlüssel Ihrer Wahl angeben, gegen den gehasht werden soll. Hier ist ein Beispiel:

Der hier verwendete Hash ist das Ergebnis der IP-Adresse und des Ports des Clients. Der optionale Parameter consistent implementiert den konsistenten Ketama-Hashing-Algorithmus. Dies sorgt für minimale Auswirkungen auf Ihren Cache, falls Sie Ihre Upstream-Server ändern.

So legen Sie die Server-Gewichtung für das Load Balancing fest

Standardmäßig wird bei der Deklaration von Backend-Servern jeder Server gleich gewichtet. Es wird davon ausgegangen, dass jeder Server über die Ressourcen und Kapazitäten verfügt, um die gleiche Last zu bewältigen, natürlich unter Berücksichtigung des im Upstream-Kontext angegebenen Load-Balancing-Algorithmus. Um dieses Standardverhalten zu ändern, können Sie bei der Deklaration jedem Server eine alternative Gewichtung zuweisen. Betrachten wir ein Beispiel:

In diesem Beispiel erhält host1.example.com doppelt so viel Datenverkehr wie die anderen beiden Server. Die Gewichtung für jeden Server ist standardmäßig eins.

Backend-Server durch Pufferung entlasten

Bei der Konfiguration des Proxyings in Ihrer Serverkonfiguration machen Sie sich vielleicht Sorgen über die Auswirkungen auf die Leistung, wenn Sie dem Prozess weitere Server hinzufügen. Glücklicherweise verfügt Nginx über Puffer- und Caching-Funktionen, die helfen können, diese Leistungsprobleme zu mindern.

Die Geschwindigkeit von zwei verschiedenen Verbindungen wird sich beim Proxying zu einem anderen Server mit Sicherheit auf das Benutzererlebnis des Clients auswirken:

  • Die erste Verbindung besteht vom Client zum Nginx-Proxy.

  • Die zweite Verbindung besteht vom Nginx-Proxy zum Backend-Upstream-Server.

Nginx kann sein Verhalten anpassen, um beide Verbindungen nach Bedarf zu optimieren.

Wenn wir Puffer entfernen, beginnt die Datenübertragung vom Upstream-Backend zum Client sofort am Nginx-Proxy. Wenn Sie wissen, dass Ihre Clients schnell sind, können Sie die Pufferung vollständig deaktivieren, um sicherzustellen, dass die Daten schnell genug beim Client ankommen. Wenn die Pufferung aktiviert ist, speichert der Nginx-Proxy die vom Backend-Upstream-Server empfangenen Antwortdaten vorübergehend. Anschließend sendet er die Daten je nach Geschwindigkeit des Clients an diesen. Sobald Nginx die Antwort in seinen Puffern hat, kann es die Verbindung zum Backend-Server schließen. Es verteilt die Daten dann mit einer vom Client unterstützten Geschwindigkeit an diesen. Gleichzeitig kann der Backend-Server weitere eingehende Anfragen verarbeiten.

Standardmäßig ist bei Nginx die Pufferung aktiviert. Das liegt daran, dass wir die Verbindungsgeschwindigkeiten der Clients nicht kennen können. Clients haben oft unterschiedliche Verbindungen, die langsamer sein können. Im Folgenden definieren wir die verschiedenen Direktiven, die wir angeben können, um das Pufferverhalten von Nginx anzupassen. Die Direktiven können im http-, server- oder location-Kontext definiert werden. Sie sollten jedoch beachten, dass die Größen-Direktiven pro Anfrage konfiguriert werden. Eine Erhöhung über das absolut Notwendige hinaus kann daher die Leistung Ihres Servers beeinträchtigen, wenn zu viele Client-Anfragen eingehen. Hier sind die Direktiven:

  • proxy_buffering – die Direktive, die steuert, ob die Pufferung für einen bestimmten Kontext und dessen Unterkontexte aktiv ist. Die Standardkonfiguration für proxy_buffering ist „on“.

  • proxy_buffer_size – die Direktive, die die Größe des Puffers zum Speichern von Headern angibt, die in einer Antwort von einem Backend-Server enthalten sind. Header bilden den ersten Teil der Antwort eines Backend-Servers. Die Pufferung dieser Header erfolgt getrennt vom Rest der Antwort. Standardmäßig entspricht die festgelegte Größe dieses Puffers der von proxy_buffers. Wenn die Header-Informationen jedoch klein sind, können Sie die Größe auf einen niedrigeren Wert einstellen.

  • proxy_buffers – die Direktive, die die Anzahl (erstes Argument) und Größe (zweites Argument) der Puffer für weitergeleitete Antworten steuert. Die Standardkonfiguration sieht 8 Puffer mit einer Größe vor, die einer Speicherseite entspricht (entweder 4k oder 8k). Sie können die Pufferung von mehr Informationen ermöglichen, indem Sie die Anzahl der Puffer erhöhen.

  • proxy_max_temp_file_size – die Direktive, die die maximale Größe einer temporären Datei auf der Festplatte pro Anfrage angibt. Temporäre Dateien werden erstellt, wenn die Upstream-Antwort zu groß ist, um in einen Puffer zu passen.

  • proxy_busy_buffers_size – die Direktive, die die maximale Größe von Puffern angibt, die als „client-ready“ und somit als belegt gelten können. Ein Client kann die Daten immer nur aus einem Puffer gleichzeitig lesen. Die Puffer befinden sich jedoch in einer Warteschlange, um in Stapeln an den Client gesendet zu werden. Sie können die Größe des Pufferbereichs, der sich in diesem Zustand befinden darf, durch Ändern dieser Direktive anpassen.

  • proxy_temp_file_write_size – die Direktive, die die Datenmenge angibt, die Nginx auf einmal in die temporäre Datei schreibt, wenn die Antwort des Backend-Upstream-Servers zu groß ist, um in die konfigurierten Puffer zu passen.

  • proxy_temp_path – die Direktive, die den Pfad zum Speicherort auf der Festplatte angibt, an dem Nginx temporäre Dateien speichern soll, wenn die Antwort des Upstream-Backend-Servers zu groß ist, um in die konfigurierten Puffer zu passen.

Nginx ist hochgradig anpassbar und bietet Ihnen mehrere Direktiven zur Feinabstimmung des Pufferungsverhaltens. In den meisten Fällen funktionieren die Standardwerte einwandfrei. Gleichzeitig ist es gut zu wissen, dass Sie einige dieser Werte für Ihre benutzerdefinierte Implementierung anpassen können. Meistens werden Sie die Direktiven proxy_buffers und proxy_buffer_size anpassen wollen.

Unten finden Sie ein Beispiel, das die Anzahl der verfügbaren Proxy-Puffer für jede Upstream-Anfrage erhöht. Gleichzeitig wird die Größe des Puffers, der die Header speichert, verringert:

Sehen wir uns an, wie Sie Daten schneller an schnelle Clients ausliefern können, indem Sie die Pufferung vollständig deaktivieren. Sollte Ihr Client nicht schnell genug sein, verwendet Nginx automatisch Puffer. Es leitet die Daten jedoch zuerst an den Client weiter, anstatt auf Puffer-Pools zu warten. Diese Konfiguration bringt einen Nachteil mit sich: Sie führt dazu, dass die Verbindung zum Upstream-Server für langsame Clients so lange geöffnet bleibt, bis der Client alle Antwortdaten empfangen hat. Wenn die Pufferung auf „off“ eingestellt ist, wird nur der durch die Direktive proxy_buffer_size definierte Puffer verwendet. Hier ist ein Ausschnitt, der zeigt, wie Sie die Pufferung deaktivieren:

  • Konfiguration einer hochverfügbaren (HA) Infrastruktur (Optionale Einrichtung)

Sie können der Nginx-Proxy-Konfiguration eine redundante Gruppe von Load Balancern hinzufügen, um sie robuster und somit hochverfügbar zu machen. Ein Hochverfügbarkeits-Setup (HA) ist eine Infrastruktur ohne Single Point of Failure. Load Balancer sind Teil dieser Konfiguration. Mit mehr als einem Load Balancer können Sie potenzielle Ausfallzeiten verhindern, wenn ein Load Balancer ausfällt oder für Wartungsarbeiten offline geht.

So implementieren Sie Nginx-Proxy-Caching zur Reduzierung der Antwortzeiten

Im vorherigen Abschnitt haben wir besprochen, wie Sie Pufferung verwenden können, um die Backend-Server zu entlasten, damit sie mehr Anfragen verarbeiten können. Nginx verfügt über eine weitere Funktion, mit der wir Antwortdaten vom Backend cachen können. Dadurch entfällt die Notwendigkeit, für alle eingehenden Anfragen eine Verbindung zum Upstream herzustellen, vollständig.

Implementierung eines Proxy-Caches

Die Direktive proxy_cache_path ermöglicht es uns, einen Cache einzurichten, indem wir einen Bereich auf der Festplatte angeben, der zum Speichern von Proxy-Inhalten verwendet werden soll. Die Direktive proxy_cache_path wird im http-Kontext definiert.

Der folgende Konfigurations-Codeausschnitt ist ein Beispiel dafür, wie Sie ein Caching-System implementieren können:

In diesem Codeausschnitt haben wir die Direktive proxy_cache_path verwendet, um ein Verzeichnis im Dateisystem zu definieren, das unseren Cache enthalten soll. Das Verzeichnis /var/lib/nginx/cache ist das Verzeichnis, das wir in diesem Fall festgelegt haben. Es steht Ihnen frei, einen Verzeichnispfad Ihrer Wahl zu definieren. Verwenden Sie die folgenden Befehle, um die von Ihnen gewählten Verzeichnisse mit den korrekten Berechtigungen und Eigentumsrechten zu erstellen:

In dem Codeausschnitt gibt der Parameter levels= die Organisation des Caches an. Nginx erstellt einen Cache-Schlüssel, indem er den Wert eines Schlüssels hasht (der mit der Direktive proxy_cache_key angegeben wird). Die von uns angegebenen Ebenen (1:2) weisen darauf hin, dass ein Verzeichnis mit einem einzelnen Zeichen (d. h. das letzte Zeichen des Hash-Werts) mit einem Unterverzeichnis mit zwei Zeichen (genommen aus den nächsten beiden Zeichen vom Ende des Hash-Werts) erstellt wird. In den meisten Fällen wird Sie das nicht betreffen. Es ist jedoch gut zu wissen, wie es Nginx hilft, die relevanten Werte schnell zu finden.

Der Parameter keys_zone= definiert den Namen für eine Cache-Zone, in unserem Fall haben wir sie backendcache genannt. Hier definieren wir auch, wie viele Metadaten wir speichern möchten. In diesem Beispiel speichern wir 8 MB an Schlüsseln. Nginx kann ungefähr 8000 Einträge pro Megabyte speichern. Der Parameter max_size gibt die maximale Größe der tatsächlich gecachten Daten an, in unserem Beispiel 50 MB.

Sie sollten auch die verwendete Direktive proxy_cache_key beachten. Diese Direktive gibt den Schlüssel an, den wir zum Speichern von gecachten Werten verwenden. Wir verwenden denselben Schlüssel, um zu prüfen, ob die Anfrage im Cache vorhanden ist. Wir haben festgelegt, dass dieser Schlüssel eine Kombination aus dem Schema (http oder https), der HTTP-Anfragemethode sowie dem angeforderten Host und der URI ist.

Zusätzlich haben wir die Direktive proxy_cache_valid verwendet. Diese Direktive kann mehrfach für verschiedene Statuscodes angegeben werden. Sie ermöglicht es uns anzugeben, wie lange Werte in Abhängigkeit vom Statuscode gespeichert werden sollen. Im Codeausschnitt haben wir 10 Minuten für Erfolgs-Codes und 1 Minute für 404-Antworten angegeben.

Da wir die Cache-Zone konfiguriert haben, besteht der nächste Schritt darin, die Konfiguration in Kraft zu setzen, indem wir Nginx mitteilen, wann der Cache verwendet werden soll. Unten finden Sie einen Konfigurationsausschnitt, der zeigt, wie wir die Verwendung dieses Caches implementieren können:

In der proxy_cache-Direktive haben wir festgelegt, dass die Cache-Zone backendcache für diesen Kontext verwendet werden soll. Wenn Sie in der Cache-Konfiguration einen anderen Namen gewählt haben, müssen Sie ihn hier ersetzen. Für jeden gültigen Eintrag prüft Nginx den Cache, bevor eine Anfrage an den Backend-Upstream-Server weitergeleitet wird.

Wir definieren die proxy_cache_bypass-Direktive, um die Variable $http_cache_control zu verwenden. Diese Variable teilt dem Server mit, ob er mit einer zwischengespeicherten Antwort oder einer neuen, nicht zwischengespeicherten Version der Ressource antworten soll. Die entsprechende Einstellung dieser Direktive ermöglicht es Nginx, verschiedene Arten von eingehenden Client-Anfragen korrekt zu verarbeiten.

Es wird auch ein zusätzlicher Header namens X-Proxy-Cache angegeben. Dieser Header hat den Wert der Variable $upstream_cache_status. Er gibt uns Auskunft darüber, ob die Anfrage zu einem Cache-Treffer (Cache Hit), einem Cache-Fehlzugriff (Cache Miss) führte oder ob der Cache explizit umgangen wurde. Solche Informationen können für den Client nützlich und bei der Fehlersuche in Anwendungen von entscheidender Bedeutung sein.

Wichtige Punkte zum Zwischenspeichern von Ergebnissen

Obwohl das Caching die Leistung Ihres Proxy-Servers erheblich verbessert, sollten Sie bei der Implementierung des Cachings Folgendes beachten:

Alle Daten, die sich auf persönliche Informationen eines Benutzers beziehen, sollten nicht zwischengespeichert werden, um Szenarien zu vermeiden, in denen die Daten eines Benutzers für einen anderen Benutzer sichtbar sind.

Ihre Backend-Server sollten alle dynamischen Elemente Ihrer Website berücksichtigen. Wir können in unserer Antwort mehrere Cache-Control-Header angeben, um unterschiedliche Zwecke zu erfüllen. Lassen Sie uns diese besprechen:

  • no-cache – gibt an, dass der Proxy prüfen muss, ob sich die Daten im Backend geändert haben, bevor er eine Antwort ausgibt. Dies ist für dynamische und wichtige Daten anwendbar. Bei jeder Anfrage wird ein ETag-gehashter Metadaten-Header überprüft, und wenn das Backend denselben Hash-Wert zurückgibt, wird der vorherige Wert bereitgestellt.

  • no-store – legt fest, dass keine empfangenen Daten zwischengespeichert werden, sodass jede Anfrage an den Server geht, um neue Daten abzurufen. Dies ist die sicherste Option für sensible Daten.

  • private – gibt an, dass kein gemeinsam genutzter Cache-Speicher die Daten zwischenspeichern darf. Sie können diesen Header verwenden, um das Caching im Browser des Benutzers festzulegen, aber auch den Proxy-Server darüber zu informieren, dass er die Daten für nachfolgende Anfragen als ungültig betrachten soll.

  • public – gibt eine öffentliche Antwort an und ermöglicht das Caching an jedem Punkt der Verbindung.

Mit dem max-age-Header können Sie in Sekunden angeben, wie lange der Cache gültig sein soll. Die oben definierten verschiedenen Header können Ihnen helfen, Caching zu implementieren und gleichzeitig sensible Daten zu schützen, dynamische Daten aktuell zu halten und vor allem die Leistung Ihres Servers zu verbessern.

Wenn auf Ihren Backend-Servern Nginx-Server laufen, können Sie innerhalb der Server-Blöcke angeben, wie lange ein Cache gültig sein soll. Sie können dies tun, indem Sie der Konfiguration die expires-Direktive hinzufügen, wie unten gezeigt:

Der erste Block ermöglicht das Zwischenspeichern von Inhalten für 59 Minuten, während der zweite Block angibt, dass kein Caching stattfinden soll. Diese Einstellungen gelten für die Optionen der Cache-Control-Header, beispielsweise „no-cache“ für den zweiten Block.

Sie können die add-header-Direktive verwenden, um zusätzliche Werte festzulegen:

Fazit

In diesem Tutorial haben wir die leistungsstarken Funktionen von Nginx kennengelernt. Nginx ist sowohl ein Webserver als auch, was am wichtigsten ist, ein Reverse-Proxy. Das Design von Nginx ermöglicht es, Tausende von gleichzeitigen Verbindungen zu verarbeiten. Dies macht es perfekt für den Lastausgleich. Aufgrund des Designs ist das Weiterleiten von Anfragen an andere Backend-Server zur Verarbeitung ziemlich unkompliziert.

Mit dem Wissen aus diesem Tutorial sollten Sie dank der Flexibilität von Nginx in der Lage sein, komplexe Proxys und Load Balancer zu implementieren.

Hier sind einige Ressourcen, die Sie auf unserem Blog finden, um sich weiter mit Nginx vertraut zu machen:

Viel Spaß beim Computing!

author

Pranay Kapgate

Autor · CloudSigma

Preslav Dobrev ist ein kreativer Designer bei CloudSigma und konzentriert sich auf eine konsistente Unternehmensidentität durch traditionelle und innovative Marketingkanäle. Er versteht es meisterhaft, künstlerische Vision mit strategischem Marketing zu verbinden, um wirkungsvolle Markengeschichten zu schaffen.

Kommentare

Noch keine Kommentare. Schreiben Sie den ersten.