Heim  >  Artikel  >  Backend-Entwicklung  >  Designprinzip des Nginx-Cache-Systems

Designprinzip des Nginx-Cache-Systems

WBOY
WBOYOriginal
2016-08-08 09:20:08914Durchsuche

Hier verwenden wir das Nginx-Cache-System als Anhaltspunkt, um das Design und die damit verbundenen Details eines Cache-Servers zu diskutieren. Aus Platzgründen werde ich nicht auf den Code eingehen Hier können Sie sich gerne gemeinsam an der Diskussion beteiligen.

Nachdem ein Cache-Server eine Datei vom Backend erhalten hat, wird sie entweder direkt an den Client gesendet (wissenschaftlicher Name ist transparente Übertragung) oder lokal zwischengespeichert. Wenn nachfolgende identische Anforderungen auf den Cache-Server zugreifen, kann die lokale Datei Eine Kopie davon ist, sofern verfügbar, direkt erhältlich. Wird durch eine nachfolgende Anfrage auf eine lokal zwischengespeicherte Datei zugegriffen, spricht man von einem Treffer im Cache. Wenn lokal keine Cache-Kopie der Datei vorhanden ist, muss der Cache-Server zum Backend gehen, um die Datei gemäß der Konfiguration abzurufen oder den Domänennamen aufzulösen. Dies wird als Cache-Miss bezeichnet. Um mehr über den Cache-Server zu erfahren, werden wir ihn bei der Analyse des Nginx-Cache-Systems ausführlich besprechen.

Das Speichersystem von Nginx ist in zwei Kategorien unterteilt. Eine wird über Proxy_Store geöffnet. Die Speichermethode besteht darin, es lokal entsprechend dem Dateipfad in der URL zu speichern. Zum Beispiel /file/2013/0001/en/test.html, dann erstellt Nginx nacheinander jedes Verzeichnis und jede Datei im angegebenen Speicherverzeichnis. Der andere Typ wird über „proxy_cache“ geöffnet. Die auf diese Weise gespeicherten Dateien werden nicht nach dem URL-Pfad organisiert, sondern mithilfe einiger spezieller Methoden (hier als benutzerdefinierte Methoden bezeichnet). Auf die benutzerdefinierten Methoden möchten wir uns konzentrieren. Was sind also die Vorteile dieser beiden Methoden?

Die Methode zum Speichern von Dateien nach URL-Pfad ist für das Programm relativ einfach zu verarbeiten, aber die Leistung ist nicht gut. Erstens sind einige URLs sehr lang. Wenn wir ein so tiefes Verzeichnis im lokalen Dateisystem erstellen müssen, ist das Öffnen und Durchsuchen von Dateien sehr langsam (erinnern Sie sich an den Prozess der Suche nach Inodes über Pfadnamen im Kernel). . Wenn Sie eine benutzerdefinierte Methode zur Verarbeitung des Musters verwenden, wird es aufgrund der URL-Länge zwar nicht von Dateien und Pfaden trennbar sein, aber weder die Komplexität erhöhen noch die Leistung verringern. In gewisser Weise handelt es sich hierbei um ein Dateisystem im Benutzermodus, und das typischste ist CFS in Squid. Die von Nginx verwendete Methode ist relativ einfach und basiert zur Verwaltung hauptsächlich auf dem MD5-Wert der URL, den wir später analysieren werden.

Caching ist untrennbar mit dem Abrufen von Inhalten aus dem Backend und dem anschließenden Senden an den Client verbunden. Es fällt jedem leicht, über die spezifische Verarbeitungsmethode nachzudenken, die gleichzeitig Empfangen und Senden sein muss. Andere Methoden wie Lesen und Senden usw. sind zu ineffizient. Lassen Sie mich hier erwähnen, dass Nginx gleichzeitig empfängt und sendet. Die verwendete Struktur ist ngx_event_pipe_t, das Medium für die Kommunikation zwischen dem Backend und dem Client. Da es sich bei der Struktur um eine allgemeine Komponente handelt, sind einige spezielle Tags erforderlich, um verwandte Funktionen im Zusammenhang mit der Speicherung abzuwickeln, sodass das zwischenspeicherbare Mitglied diese wichtige Aufgabe übernimmt.

p->cacheable = u->cacheable ||. u->store;

Das heißt, wenn Cacheable 1 ist, muss es gespeichert werden, andernfalls wird es nicht gespeichert gelagert. Wofür stehen also u->cacheable und u->store? Sie repräsentieren jeweils die beiden zuvor erwähnten Methoden, nämlich Proxy_cache und Proxy_store.

(Um etwas Wissen hinzuzufügen: Wenn Nginx Back-End-Daten abruft, wird sein Verhalten durch Proxy_Buffering gesteuert, wodurch die Antwortpufferung für den Back-End-Server aktiviert wird. Wenn die Pufferung aktiviert ist, geht Nginx davon aus, dass der Proxy Der Server kann die Antwort sehr schnell liefern und in einen Puffer legen. Wenn die Antwort nicht in den Speicher passt, wird sie auf die Festplatte geschrieben vom Backend wird sofort übertragen)


Dies sind alles Randbemerkungen, wir haben den Kern der Nginx-Cache-Funktion noch nicht berührt. Aus Sicht der Implementierung gibt es in der Nginx-Upstream-Struktur ein Mitglied namens Cache, dessen Typ ngx_shm_zone_t ist. Wenn wir die Cache-Funktion aktivieren, wird das Cache-Mitglied zum Verwalten des gemeinsam genutzten Speichers verwendet (warum wird gemeinsam genutzter Speicher verwendet?), und das Mitglied ist NULL, wenn es auf andere Weise gespeichert wird. Ein weiterer Punkt, der erklärt werden muss, ist, dass eine Datei im Cache-System normalerweise als Speicherobjekt, also als Cache-Objekt, bezeichnet wird. Sie müssen also vor dem Zwischenspeichern ein Speicherobjekt erstellen. Eine wichtige Frage ist, wie man den Zeitpunkt für die Erstellung wählt. Was denken Sie darüber? Zuerst müssen wir prüfen, ob eine Datei zwischengespeichert werden muss. Offensichtlich müssen mit der GET-Methode angeforderte Dateien im Allgemeinen zwischengespeichert werden. Wenn wir also in der frühen Phase der Anforderungsverarbeitung die GET-Methode sehen, können wir zuerst ein Objekt erstellen. Aber oft kann selbst eine von einer GET-Methode angeforderte Datei nicht zwischengespeichert werden. Wenn Sie das Objekt vorzeitig erstellen, verschwenden Sie nicht nur Zeit und Platz, sondern zerstören es am Ende auch. Was beeinflusst also die Speicherung von GET-Anfragen? Das ist das Cache-Control-Feld im Antwortheader. Dieses Feld teilt dem Proxy oder Browser mit, ob die Datei zwischengespeichert werden kann. Im Allgemeinen werden Cache-Server Anfragen standardmäßig zwischenspeichern, wenn im Antwortheader kein Cache-Kontrollfeld vorhanden ist.

Basierend auf dieser Überlegung erstellt der von uns entwickelte Cache-Server erst Cache-Objekte, nachdem der Antwortheader analysiert wurde und ausreichende Beweise für die Cachefähigkeit vorliegen. Leider macht Nginx dies nicht.

nginx schließt die Erstellung von Cache-Objekten in der Funktion ngx_http_upstream_init_request ab. In welcher Phase der http-Verarbeitung befindet sich diese Funktion? bevor eine Verbindung mit dem Backend hergestellt wird. Ich persönlich denke, dass dieser Ort nicht geeignet ist. . . Was denken Sie?

Bezüglich des Erstellungsprozesses können Sie die Funktion ngx_http_upstream_cache lesen. Hier werde ich unseren Cache analysieren, indem ich ihn mit Nginx vergleiche. Unsere Anfrage verwendet ein Mitglied namens „store“, um Kontakt mit dem Cache-Objekt herzustellen. Das Gleiche gilt für Nginx, dessen Anforderungsstruktur über ein Cache-Mitglied verfügt, um dasselbe zu tun. Der Unterschied besteht darin, dass sich der Speicherplatz, der unseren Store-Mitgliedern entspricht, im gemeinsamen Speicher befindet, während Nginx ihn in r->pool beantragt (warum machen wir das?).

Im nächsten Schritt muss Nginx den Schlüssel des Cache-Objekts gemäß der hier verwendeten Konfiguration generieren. Dieser Schlüssel dient als eindeutige Kennung eines Cache-Objekts im System. Viele Menschen sind möglicherweise besorgt über MD5-Kollisionen. Ich denke, dass diese Anforderung hier völlig akzeptabel ist, wenn sie nicht besonders anspruchsvoll ist und die Verarbeitung relativ einfach ist.

Was später geklärt werden muss, ist, wie die Datei auf der Festplatte gespeichert werden soll.

Nehmen wir ein Beispiel, das wir zuvor verwendet haben: /file/2013/0001/en/test.html. Der entsprechende MD5-Wert ist 8ef9229f02c5672c747dc7a324d658d0. Tatsächlich verwendet Nginx ihn als Dateinamen. Reicht das? Was passiert, wenn wir ein Verzeichnis zum Speichern von Dateien finden und darin eine Reihe solcher Dateien vorhanden sind? Wir wissen, dass die meisten Dateisysteme Beschränkungen hinsichtlich der Anzahl der Dateien in einem einzelnen Verzeichnis haben, sodass eine derart einfache und grobe Verarbeitung nicht möglich ist. Was zu tun? Mit Nginx können Sie durch Konfiguration mehrstufige Verzeichnisse verwenden, um dieses Problem zu lösen. Um es einfach auszudrücken: Nginx verwendet die Levels-Direktive, um die Anzahl der Verzeichnisebenen (durch Doppelpunkte getrennt) und die Anzahl der Zeichen in jedem Verzeichnisnamen anzugeben. In unserem Beispiel wird davon ausgegangen, dasslevels=1:2 konfiguriert ist, was bedeutet, dass a Es wird ein Verzeichnis mit zwei Ebenen verwendet. Der Verzeichnisname der ersten Ebene besteht aus einem Zeichen und der Verzeichnisname der zweiten Ebene besteht aus zwei Zeichen. Nginx unterstützt jedoch bis zu drei Verzeichnisebenen, nämlich Ebenen=xxx:xxx:xxx.

Woher kommen also die Zeichen, aus denen der Verzeichnisname besteht? Angenommen, unser Speicherverzeichnis ist /cache, Ebenen=1:2, dann wird die obige Datei wie folgt gespeichert:

/cache/0 / 8d/8ef9229f02c5672c747dc7a324d658d0

Sehen Sie, wie die beiden Verzeichnisnamen 0 und 8d herkamen. Nun, das ist nicht nötig zu erklären. Nachdem das Objekt erstellt wurde, müssen Sie die Objektverwaltungsstruktur zwischenspeichern, die von ngx_http_file_cache_exists verwaltet wird.

Was ist zu tun, wenn das aktuelle Verzeichnis und die Dateien beim Erstellen dieser Datei bereits vorhanden sind? Sie können den Code durchgehen und sehen, wie Nginx damit umgeht.

Tatsächlich ist jetzt alles Vorbereitungsarbeit Ankunft von Back-End-Inhalten.

Erweiterte Lektüre:

http://www.pagefault.info/?p=123

http://www.pagefault.info/?p=375

Das Obige hat die Designprinzipien des Nginx-Cache-Systems einschließlich seiner Aspekte vorgestellt. Ich hoffe, dass es für Freunde hilfreich sein wird, die sich für PHP-Tutorials interessieren.

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:PHP-regulärer AusdruckNächster Artikel:PHP-regulärer Ausdruck