Heute sprechen wir über Anfragen. In Nginx beziehen wir uns auf http-Anfragen. Die spezifische Datenstruktur in Nginx ist ngx_http_request_t. ngx_http_request_t ist eine Kapselung einer http-Anfrage. Wir wissen, dass eine HTTP-Anfrage eine Anforderungszeile, einen Anforderungsheader, einen Anforderungstext, eine Antwortzeile, einen Antwortheader und einen Antworttext umfasst.
HTTP-Anfrage ist ein typisches Netzwerkprotokoll vom Typ „Anfrage/Antwort“, und http ist ein Textprotokoll. Daher analysieren wir die Anforderungszeile und den Anforderungsheader und geben die Antwortzeile und den Antwortheader häufig Zeile für Zeile aus mit. (Empfohlenes Lernen: Nginx-Verwendung)
Wenn wir selbst einen http-Server schreiben, sendet der Client normalerweise nach dem Herstellen einer Verbindung eine Anfrage. Dann lesen wir eine Datenzeile und analysieren die in der Anforderungszeile enthaltenen Methoden-, URI- und http_version-Informationen.
Verarbeiten Sie dann die Anforderungsheader Zeile für Zeile und bestimmen Sie anhand der Anforderungsmethode und der Anforderungsheaderinformationen, ob ein Anforderungstext vorhanden ist, sowie die Länge des Anforderungstexts und lesen Sie dann den Anforderungstext.
Nachdem wir die Anfrage erhalten haben, verarbeiten wir die Anfrage, um die auszugebenden Daten zu generieren, und generieren dann die Antwortzeile, den Antwortheader und den Antworttext.
Nachdem die Antwort an den Kunden gesendet wurde, wird eine vollständige Anfrage bearbeitet. Dies ist natürlich die einfachste Webserver-Verarbeitungsmethode, mit einigen geringfügigen Unterschieden. Wenn beispielsweise der Anforderungsheader gelesen wird, beginnt die Anforderungsverarbeitung. Nginx verwendet ngx_http_request_t, um Daten im Zusammenhang mit Analyseanforderungen und Ausgabeantworten zu speichern.
Lassen Sie uns als Nächstes kurz darüber sprechen, wie Nginx eine vollständige Anfrage verarbeitet. Für Nginx beginnt eine Anfrage bei ngx_http_init_request. In dieser Funktion wird das Leseereignis auf ngx_http_process_request_line gesetzt. Das heißt, das nächste Netzwerkereignis wird von ngx_http_process_request_line ausgeführt.
Aus dem Funktionsnamen von ngx_http_process_request_line können wir ersehen, dass es sich hierbei um die Verarbeitung der Anforderungszeile handelt. Wie bereits erwähnt, besteht das erste, was bei der Verarbeitung einer Anforderung zu tun ist, darin, die Anforderungszeile zu verarbeiten.
Anforderungsdaten über ngx_http_read_request_header lesen. Anschließend wird die Funktion ngx_http_parse_request_line aufgerufen, um die Anforderungszeile zu analysieren. Um die Effizienz zu verbessern, verwendet Nginx eine Zustandsmaschine zum Parsen der Anforderungszeile. Beim Vergleich von Methoden wird kein direkter String-Vergleich durchgeführt. Stattdessen werden vier Zeichen in eine Ganzzahl umgewandelt und dann einmal verglichen, um die Anzahl der CPU-Anweisungen zu reduzieren . Das wurde schon einmal gesagt.
Viele Leute wissen vielleicht, dass eine Anforderungszeile die Anforderungsmethode, die URL und die Version enthält, aber sie wissen nicht, dass die Anforderungszeile auch den Host enthalten kann. Beispielsweise ist eine Anfrage wie GET http://www.taobao.com/uri HTTP/1.0 ebenfalls zulässig, und der Host ist www.taobao.com. Zu diesem Zeitpunkt ignoriert Nginx das Hostfeld im Anfrageheader und verwenden Sie „Use this“ in der Anforderungszeile, um den virtuellen Host zu finden.
Darüber hinaus werden für die http0.9-Version Anforderungsheader nicht unterstützt, sodass hier eine besondere Behandlung erforderlich ist. Daher lautet die Protokollversion beim späteren Parsen des Anforderungsheaders 1.0 oder 1.1. Die aus der gesamten Anforderungszeile analysierten Parameter werden in der Struktur ngx_http_request_t gespeichert.
Nach dem Parsen der Anforderungszeile setzt Nginx den Handler des Leseereignisses auf ngx_http_process_request_headers, und nachfolgende Anforderungen werden dann in ngx_http_process_request_headers gelesen und analysiert.
Die Funktion ngx_http_process_request_headers wird zum Lesen von Anforderungsheadern verwendet. Sie ruft weiterhin ngx_http_read_request_header auf, um die Anforderungsheader zu lesen, und ruft ngx_http_parse_header_line auf, um eine Zeile mit Anforderungsheadern zu analysieren In der Domäne headers_in von ngx_http_request_t ist headers_in eine verknüpfte Listenstruktur, die alle Anforderungsheader speichert.
Einige Anforderungen in HTTP erfordern eine spezielle Verarbeitung. Diese Anforderungsheader und Anforderungsverarbeitungsfunktionen werden in einer Zuordnungstabelle gespeichert, nämlich ngx_http_headers_in. Während der Initialisierung wird eine Hash-Tabelle generiert Im Header wird zunächst die Hash-Tabelle durchsucht. Wenn sie gefunden wird, wird die entsprechende Verarbeitungsfunktion aufgerufen, um den Anforderungsheader zu verarbeiten. Beispiel: Die Verarbeitungsfunktion des Host-Headers lautet ngx_http_process_host.
Wenn Nginx zwei Wagenrückläufe und Zeilenvorschübe analysiert, zeigt dies das Ende des Anforderungsheaders an. Zu diesem Zeitpunkt wird ngx_http_process_request aufgerufen, um die Anforderung zu verarbeiten.
ngx_http_process_request setzt die Lese- und Schreibereignishandlerfunktion der aktuellen Verbindung auf ngx_http_request_handler und ruft dann ngx_http_handler auf, um tatsächlich mit der Verarbeitung einer vollständigen http-Anfrage zu beginnen.
Dies kann seltsam sein. Die Lese- und Schreibereignisverarbeitungsfunktionen sind beide ngx_http_request_handler. Tatsächlich wird in dieser Funktion der read_event_handler bzw. write_event_handler in ngx_http_request_t aufgerufen ein Schreibereignis.
Da zu diesem Zeitpunkt unser Anforderungsheader gelesen wurde, besteht der Ansatz von Nginx nicht darin, zuerst den Anforderungstext zu lesen. Daher setzen wir hier read_event_handler auf ngx_http_block_reading, d. h. es werden keine Daten gelesen.
Wie gerade erwähnt, liegt der eigentliche Beginn der Datenverarbeitung in der Funktion ngx_http_handler. Diese Funktion setzt write_event_handler auf ngx_http_core_run_phases und führt die Funktion ngx_http_core_run_phases aus.
ngx_http_core_run_phases Diese Funktion führt eine mehrstufige Anforderungsverarbeitung durch. Nginx unterteilt die Verarbeitung einer http-Anfrage in mehrere Phasen. Anschließend führt diese Funktion diese Phasen aus, um Daten zu generieren.
Da ngx_http_core_run_phases schließlich Daten generiert, ist es für uns leicht zu verstehen, warum die Schreibereignisverarbeitungsfunktion auf ngx_http_core_run_phases eingestellt ist.
Hier erkläre ich kurz die Aufruflogik der Funktion. Wir müssen verstehen, dass ngx_http_core_run_phases letztendlich aufgerufen wird, um die Anfrage zu verarbeiten. Der generierte Antwortheader wird in den headers_out von ngx_http_request_t eingefügt im Lassen Sie uns im Prozess der Anforderungsbearbeitung darüber sprechen. Nginx verarbeitet die Anforderung in verschiedenen Phasen und ruft schließlich den Filter auf, um die Daten zu filtern und zu verarbeiten, z. B. verkürzte Übertragung, GZIP-Komprimierung usw.
Der Filter umfasst hier den Header-Filter und den Body-Filter, die den Antwort-Header oder Antwort-Body verarbeiten. Filter ist eine verknüpfte Listenstruktur mit Header-Filter und Body-Filter. Zuerst werden alle Filter im Header-Filter ausgeführt, und dann werden alle Filter im Body-Filter ausgeführt.
Der letzte Filter im Header-Filter ist ngx_http_header_filter. Dieser Filter durchläuft alle Antwortheader, die ausgegeben werden müssen, und ruft dann ngx_http_write_filter zur Ausgabe auf.
ngx_http_write_filter ist der letzte im Körperfilter, daher rufen die ersten Körperinformationen von Nginx nach dem Durchlaufen einer Reihe von Körperfiltern schließlich ngx_http_write_filter zur Ausgabe auf (es gibt ein Bild zur Veranschaulichung).
Hier ist zu beachten, dass Nginx den gesamten Anforderungsheader in einen Puffer legt. Die Größe dieses Puffers wird über das Konfigurationselement client_header_buffer_size festgelegt, wenn der Anforderungsheader des Benutzers zu groß ist und dieser Puffer nicht hineinpasst Dann weist Nginx einen neuen größeren Puffer zu, um den Anforderungsheader zu speichern. Die Puffergruppe „large_buffer“ bedeutet beispielsweise, dass vier 8-KByte-Puffer verfügbar sind.
Beachten Sie, dass zur Wahrung der Integrität der Anforderungszeile oder des Anforderungsheaders eine vollständige Anforderungszeile oder ein vollständiger Anforderungsheader in einem kontinuierlichen Speicher abgelegt werden muss. Daher wird eine vollständige Anforderungszeile oder ein vollständiger Anforderungsheader nur gespeichert in einem Puffer.
Auf diese Weise wird ein 414-Fehler zurückgegeben, wenn die Anforderungszeile größer als die Puffergröße ist. Wenn die Anforderungsheadergröße größer als die Puffergröße ist, wird ein 400-Fehler zurückgegeben. Nachdem wir die Werte dieser Parameter und die tatsächlichen Praktiken von Nginx im Anwendungsszenario verstanden haben, müssen wir diese Parameter entsprechend den tatsächlichen Anforderungen anpassen, um unser Programm zu optimieren.
Verarbeitungsflussdiagramm:
Das Obige ist der Lebenszyklus einer http-Anfrage in Nginx.
Das obige ist der detaillierte Inhalt vonWie gehe ich mit Nginx-Anfragen um?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!