Nginx-Module sind im Allgemeinen in drei Kategorien unterteilt: Handler, Filter und Upstream. In den vorherigen Kapiteln haben die Leser bereits etwas über Handler und Filter gelernt. Mit diesen beiden Modultypen kann Nginx problemlos jede eigenständige Arbeit erledigen.
Das Upstream-Modul ermöglicht es Nginx, die Einschränkungen einer einzelnen Maschine zu überwinden und den Empfang, die Verarbeitung und die Weiterleitung von Netzwerkdaten abzuschließen.
Die Datenweiterleitungsfunktion bietet Nginx horizontale Verarbeitungsfunktionen auf einer einzelnen Maschine, wodurch Nginx von der Einschränkung befreit wird, nur eine einzige Funktion für Endknoten bereitzustellen, und ihm die Funktionen des Teilens, Kapselns und Integrierens gleichzeitig ermöglicht Netzwerkanwendungsebene.
Datenweiterleitung ist eine Schlüsselkomponente der Fähigkeit von Nginx, eine Netzwerkanwendung zu erstellen. Aus Gründen der Entwicklungskosten werden Schlüsselkomponenten einer Netzwerkanwendung natürlich zunächst häufig mit höheren Programmiersprachen entwickelt. Wenn das System jedoch eine bestimmte Größe erreicht und mehr Wert auf Leistung gelegt wird, müssen die in Hochsprachen entwickelten Komponenten strukturell geändert werden, um die erforderlichen Leistungsziele zu erreichen.
In Bezug auf die Änderungskosten zeigt das Upstream-Modul von Nginx derzeit seine Vorteile, da es von Natur aus schnell ist. Abgesehen davon macht die hierarchische und lose Kopplung, die das Konfigurationssystem von nginx bietet, das System auf einem relativ hohen Niveau skalierbar.
Im Wesentlichen gehört Upstream zum Handler, generiert jedoch keinen eigenen Inhalt, sondern erhält Inhalte durch Anforderung des Back-End-Servers, daher wird er Upstream (Upstream) genannt. Der gesamte Prozess des Anforderns und Erhaltens von Antwortinhalten wurde in Nginx gekapselt, sodass das Upstream-Modul nur mehrere Rückruffunktionen entwickeln muss, um bestimmte Aufgaben wie das Erstellen von Anforderungen und das Parsen von Antworten abzuschließen.
Rückruffunktionen des Upstream-Moduls sind wie folgt aufgeführt:
Funktionsname | Beschreibung |
---|---|
create_request | create_request |
reinit_request | |
process_header | |
finalize_request | |
input_filter_init | |
Memcached-Modulanalyse
Das Upstream-Modul verwendet die Zugriffsmethode des Handler-Moduls. Gleichzeitig folgt das Design des Befehlssystems des Upstream-Moduls auch den Grundregeln des Handler-Moduls: Das Modul wird erst nach der Konfiguration des Moduls ausgeführt. Was ist also das Besondere am Upstream-Modul? Das ist die Verarbeitungsfunktion des Upstream-Moduls. Die von der Verarbeitungsfunktion des Upstream-Moduls ausgeführten Vorgänge umfassen einen festen Prozess: (Nehmen Sie das Memcached-Modul in der Verarbeitungsfunktion ngx_http_memcached_handler von Memcached) Erstellen Sie die Upstream-Datenstruktur : ngx_http_upstream_t *u; if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u = r->upstream; Nach dem Login kopieren Legen Sie das Modul-Tag und das Schema fest. Das Schema wird jetzt nur für Protokolle verwendet und Tags werden für die buf_chain-Verwaltung verwendet: ngx_str_set(&u->schema, "memcached://"); u->output.tag = (ngx_buf_tag_t) &ngx_http_memcached_module; Nach dem Login kopieren Legen Sie die Datenstruktur der Back-End-Serverliste des Upstreams fest: mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module); u->conf = &mlcf->upstream; Nach dem Login kopieren Setzen Sie die Upstream-Rückruffunktion fest: u->create_request = ngx_http_memcached_create_request; u->reinit_request = ngx_http_memcached_reinit_request; u->process_header = ngx_http_memcached_process_header; u->abort_request = ngx_http_memcached_abort_request; u->finalize_request = ngx_http_memcached_finalize_request; u->input_filter_init = ngx_http_memcached_filter_init; u->input_filter = ngx_http_memcached_filter; Nach dem Login kopieren Erstellen und richten Sie die Datenstruktur der Upstream-Umgebung ein: ctx = ngx_palloc(r->pool, sizeof(ngx_http_memcached_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->request = r; ngx_http_set_ctx(r, ctx, ngx_http_memcached_module); u->input_filter_ctx = ctx; Nach dem Login kopieren Schließen Sie die Upstream-Initialisierung ab und beenden Sie die Arbeit: r->main->count++; ngx_http_upstream_init(r); return NGX_DONE; Nach dem Login kopieren Dies gilt für jedes Upstream-Modul, so einfach wie Memcached, so komplex wie Proxy und FastCGI. Schritte 2 und 4 sind leicht zu verstehen. Die von verschiedenen Modulen gesetzten Flags und die verwendeten Rückruffunktionen sind definitiv unterschiedlich. Auch Schritt 5 ist nicht schwer zu verstehen. Nur Schritt 3 ist etwas verwirrend. Verschiedene Module verfolgen sehr unterschiedliche Strategien beim Abrufen der Backend-Serverliste. Einige sind so einfach und klar wie Memcached, andere sind so logisch komplex wie Proxy. Schritt 6 ist normalerweise zwischen verschiedenen Modulen konsistent. Erhöhen Sie die Anzahl um 1 und geben Sie NGX_DONE zurück. Rückruffunktion: (immer noch die Verarbeitungsfunktion des Memcached-Moduls als Beispiel)
#define LF (u_char) '\n' for (p = u->buffer.pos; p < u->buffer.last; p++) { if (*p == LF) { goto found; } } Nach dem Login kopieren Wenn das LF-Zeichen („n’] nicht in den Daten gefunden wird, die in den Puffer eingelesen wurden Die Funktion gibt NGX_AGAIN zurück, was darauf hinweist, dass der Header nicht vollständig gelesen wurde und mit dem Lesen der Daten fortgefahren werden muss. Nginx ruft diese Funktion erneut auf, nachdem neue Daten empfangen wurden. nginx verwendet bei der Verarbeitung der Antwortheader des Backend-Servers nur einen Cache. Alle Daten befinden sich in diesem Cache, sodass beim Parsen der Header-Informationen nicht berücksichtigt werden muss, dass sich die Header-Informationen über mehrere Caches erstrecken. Wenn der Header zu groß ist und nicht in diesem Cache gespeichert werden kann, gibt Nginx eine Fehlermeldung an den Client zurück und zeichnet ein Fehlerprotokoll auf, das darauf hinweist, dass der Cache nicht groß genug ist. Die wichtige Aufgabe von ngx_http_memcached_process_header besteht darin, den vom Backend-Server zurückgegebenen Status in den an den Client zurückgegebenen Status zu übersetzen. Beispiel: u->headers_in.content_length_n = ngx_atoof(start, p - start); ··· u->headers_in.status_n = 200; u->state->status = 200; ··· u->headers_in.status_n = 404; u->state->status = 404; Nach dem Login kopieren u->state wird zur Berechnung von Upstream-bezogenen Variablen verwendet. Beispielsweise wird u->state->status verwendet, um den Wert der Variablen „upstream_status“ zu berechnen. u->headers_in wird als Statuscode in der Antwort an den Client zurückgegeben. Und u->headers_in.content_length_n legt die Länge der an den Client zurückgegebenen Antwort fest. In dieser Funktion müssen Sie den Lesezeiger pos nach der Verarbeitung der Header-Informationen nach hinten verschieben, da diese Daten sonst auch in den Hauptteil der an den Client zurückgegebenen Antwort kopiert werden, was zu einem falschen Hauptinhalt führt. Die Funktion ngx_http_memcached_process_header schließt die korrekte Verarbeitung des Antwortheaders ab und sollte NGX_OK zurückgeben. Wenn NGX_AGAIN zurückgegeben wird, bedeutet dies, dass nicht die vollständigen Daten gelesen wurden und die Daten weiterhin vom Backend-Server gelesen werden müssen. Die Rückgabe von NGX_DECLINED ist bedeutungslos. Jeder andere Rückgabewert wird als Fehlerstatus betrachtet und nginx beendet die Upstream-Anfrage und gibt eine Fehlermeldung zurück. ngx_http_memcached_filter_init: Korrigieren Sie die vom Backend-Server empfangene Inhaltslänge. Denn dieser Teil der Länge wird bei der Verarbeitung des Headers nicht addiert. ngx_http_memcached_filter: Die eigentliche Bedeutung der Textverarbeitung besteht darin, den gültigen Inhalt des vom Back-End-Server empfangenen Texts in ngx_chain_t zu kapseln und ihn am Ende von u->out_bufs hinzuzufügen. nginx kopiert keine Daten, sondern erstellt die Datenstruktur ngx_buf_t, um auf diese Datenspeicherbereiche zu verweisen, und organisiert diese Puffer dann nach ngx_chain_t. Diese Implementierung vermeidet eine groß angelegte Speicherverlagerung und ist einer der Gründe, warum Nginx effizient ist. |
Das obige ist der detaillierte Inhalt vonSo verwenden Sie das Upstream-Modul in Nginx. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!