Wenn wir NGINX-Benutzern bei Problemen helfen, sehen wir häufig dieselben Konfigurationsfehler, die wir schon oft in den Konfigurationen anderer Benutzer gesehen haben – manchmal sogar in Konfigurationen, die von anderen NGINX-Ingenieuren geschrieben wurden! In diesem Blog sehen wir uns die zehn häufigsten Fehler an und erklären, was falsch ist und wie man es behebt.
error_log
off-
DirektiveProxy_Buffering
Off
-Direktiveif-
Direktiveip_hash
, wenn der gesamte Datenverkehr aus demselben /24 CIDR-Block stammtDie Direktive worker_connections
legt die maximale Anzahl gleichzeitiger Verbindungen fest, die ein NGINX-Arbeitsprozess geöffnet haben kann (der Standardwert ist 512). Auf das Maximum werden alle Verbindungstypen angerechnet (z. B. Verbindungen mit Proxy-Servern), nicht nur Client-Verbindungen. Man sollte jedoch bedenken, dass es letztlich noch eine weitere Beschränkung für die Anzahl gleichzeitiger Verbindungen pro Worker gibt: die Beschränkung des Betriebssystems hinsichtlich der maximalen Anzahl von Datei-Deskriptoren (FDs), die jedem Prozess zugewiesen werden. In modernen UNIX-Distributionen liegt die Standardgrenze bei 1024.
Für alle NGINX-Bereitstellungen außer den kleinsten ist ein Limit von 512 Verbindungen pro Worker wahrscheinlich zu niedrig. Tatsächlich erhöht die Standarddatei nginx.conf, die wir mit den NGINX Open Source-Binärdateien und NGINX Plus verteilen, diesen Wert auf 1024.
Der häufigste Konfigurationsfehler besteht darin, das Limit für FDs nicht mindestens auf den doppelten Wert von worker_connections
zu erhöhen. Die Lösung besteht darin, diesen Wert mit der Direktive worker_rlimit_nofile
im Hauptkonfigurationskontext festzulegen.
Aus diesem Grund werden mehr FDs benötigt: Jede Verbindung von einem NGINX-Arbeitsprozess zu einem Client oder Upstream-Server verbraucht ein FD. Wenn NGINX als Webserver fungiert, verwendet es ein FD für die Client-Verbindung und ein FD pro bereitgestellter Datei, also mindestens zwei FDs pro Client (die meisten Webseiten bestehen jedoch aus vielen Dateien). Wenn NGINX als Proxyserver fungiert, verwendet es jeweils ein FD für die Verbindung zum Client und zum Upstream-Server und möglicherweise ein drittes FD für die Datei, in der die Antwort des Servers vorübergehend gespeichert wird. Als Caching-Server verhält sich NGINX für zwischengespeicherte Antworten wie ein Webserver und wie ein Proxyserver, wenn der Cache leer oder abgelaufen ist.
NGINX verwendet auch ein FD pro Protokolldatei und einige FDs zur Kommunikation mit dem Masterprozess, aber normalerweise sind diese Zahlen gering im Vergleich zur Anzahl der für Verbindungen und Dateien verwendeten FDs.
UNIX bietet mehrere Möglichkeiten, die Anzahl der FDs pro Prozess festzulegen:
ulimit
-Befehl, wenn Sie NGINX von einer Shell aus startenInit
-Skript oder die Manifestvariablen des systemd-
Dienstes, wenn Sie NGINX als Dienst startenDie zu verwendende Methode hängt jedoch davon ab, wie Sie NGINX starten, wohingegen worker_rlimit_nofile
unabhängig davon funktioniert, wie Sie NGINX starten.
Es gibt auch eine systemweite Beschränkung der Anzahl von FDs, die Sie mit dem Befehl sysctl
fs.file-max
des Betriebssystems festlegen können. Normalerweise ist es groß genug, es lohnt sich jedoch zu überprüfen, dass die maximale Anzahl an Datei-Deskriptoren, die alle NGINX-Arbeitsprozesse verwenden können ( worker_rlimit_nofile
*
worker_processes
), deutlich kleiner ist als fs.file‑max
. Wenn NGINX aus irgendeinem Grund alle verfügbaren FDs verwendet (beispielsweise während eines DoS-Angriffs), wird es unmöglich, sich auch nur beim Computer anzumelden, um das Problem zu beheben.
error_log
off-
DirektiveDer häufigste Fehler besteht in der Annahme, dass die Direktive error_log
off
die Protokollierung deaktiviert. Tatsächlich übernimmt error_log
im Gegensatz zur access_log-
Direktive keinen Off-
Parameter. Wenn Sie die Direktive error_log
off
in die Konfiguration aufnehmen, erstellt NGINX eine Fehlerprotokolldatei mit dem Namen off im Standardverzeichnis für NGINX-Konfigurationsdateien (normalerweise /etc/nginx ).
Wir empfehlen nicht, das Fehlerprotokoll zu deaktivieren, da es eine wichtige Informationsquelle beim Debuggen von Problemen mit NGINX ist. Wenn der Speicherplatz jedoch so begrenzt ist, dass möglicherweise so viele Daten protokolliert werden können, dass der verfügbare Speicherplatz erschöpft ist, kann es sinnvoll sein, die Fehlerprotokollierung zu deaktivieren. Fügen Sie diese Anweisung in den Hauptkonfigurationskontext ein:
Fehlerprotokoll /dev/null Notfall;
Beachten Sie, dass diese Anweisung erst gilt, wenn NGINX die Konfiguration gelesen und validiert hat. Daher kann es sein, dass bei jedem Start von NGINX oder Neuladen der Konfiguration die Protokollierung am Standardspeicherort für Fehlerprotokolle (normalerweise /var/log/nginx/error.log ) erfolgt, bis die Konfiguration validiert ist. Um das Protokollverzeichnis zu ändern, schließen Sie die -e
<Fehlerprotokollspeicherort>
Parameter auf der nginx
Befehl.
Standardmäßig öffnet NGINX für jede neue eingehende Anfrage eine neue Verbindung zu einem Upstream-Server (Backend-Server). Dies ist sicher, aber ineffizient, da NGINX und der Server drei Pakete austauschen müssen, um eine Verbindung herzustellen, und drei oder vier, um sie zu beenden.
Bei hohem Datenverkehr kann das Öffnen einer neuen Verbindung für jede Anforderung die Systemressourcen erschöpfen und dazu führen, dass überhaupt keine Verbindungen mehr geöffnet werden können. Und zwar aus folgendem Grund: Für jede Verbindung muss das 4-Tupel aus Quelladresse, Quellport, Zieladresse und Zielport eindeutig sein. Bei Verbindungen von NGINX zu einem Upstream-Server sind drei der Elemente (das erste, dritte und vierte) festgelegt, sodass nur der Quellport als Variable übrig bleibt. Wenn eine Verbindung geschlossen wird, befindet sich der Linux-Socket zwei Minuten lang im Zustand TIME-WAIT
, wodurch bei hohem Datenverkehr die Möglichkeit steigt, dass der Pool verfügbarer Quell-Ports erschöpft wird. In diesem Fall kann NGINX keine neuen Verbindungen zu Upstream-Servern herstellen.
Die Lösung besteht darin, Keepalive-Verbindungen zwischen NGINX und Upstream-Servern zu aktivieren – anstatt sie nach Abschluss einer Anforderung zu schließen, bleibt die Verbindung offen und kann für weitere Anforderungen verwendet werden. Dadurch wird die Möglichkeit einer Erschöpfung der Quellports verringert und die Leistung verbessert .
So aktivieren Sie Keepalive-Verbindungen:
Fügen Sie die Direktive „Keepalive“
in jeden Upstream{}-
Block ein, um die Anzahl der inaktiven Keepalive-Verbindungen zu Upstream-Servern festzulegen, die im Cache jedes Arbeitsprozesses gespeichert werden.
Beachten Sie, dass die Keepalive
-Direktive die Gesamtzahl der Verbindungen zu Upstream-Servern, die ein NGINX-Arbeitsprozess öffnen kann, nicht begrenzt – das ist ein weit verbreiteter Irrtum. Daher muss der Parameter für Keepalive
nicht so groß sein, wie Sie vielleicht denken.
Wir empfehlen, den Parameter auf die doppelte Anzahl der im Upstream{}-
Block aufgelisteten Server zu setzen. Dies ist groß genug, damit NGINX Keepalive-Verbindungen mit allen Servern aufrechterhalten kann, aber klein genug, damit Upstream-Server auch neue eingehende Verbindungen verarbeiten können.
Beachten Sie auch, dass, wenn Sie einen Lastausgleichsalgorithmus im Block upstream{}
angeben – mit der Direktive hash
, ip_hash
, least_conn
, least_time
oder random
– die Direktive über der Direktive keepalive
erscheinen muss. Dies ist eine der seltenen Ausnahmen von der allgemeinen Regel, dass die Reihenfolge der Anweisungen in der NGINX-Konfiguration keine Rolle spielt.
Fügen Sie im Location{}
-Block, der Anfragen an eine Upstream-Gruppe weiterleitet, neben der Proxy_pass-
Direktive die folgenden Anweisungen ein:
proxy_http_version 1.1;
proxy_set_header "Verbindung" "";
Standardmäßig verwendet NGINX HTTP/1.0 für Verbindungen zu Upstream-Servern und fügt den Anfragen, die es an die Server weiterleitet, dementsprechend den Header „Connection:
close“
hinzu. Das Ergebnis ist, dass jede Verbindung geschlossen wird, wenn die Anforderung abgeschlossen ist, trotz des Vorhandenseins der Keepalive-
Direktive im Upstream{}-
Block.
Die Direktive proxy_http_version
weist NGINX an, stattdessen HTTP/1.1 zu verwenden, und die Direktive proxy_set_header
entfernt den Close-
Wert aus dem Connection-
Header.
NGINX-Direktiven werden nach unten oder „von außen nach innen“ vererbt: Ein untergeordneter Kontext – also ein Kontext, der in einem anderen Kontext (seinem übergeordneten Kontext ) verschachtelt ist – erbt die Einstellungen der Direktiven, die auf der übergeordneten Ebene enthalten sind. Beispielsweise erben alle Server{}-
und Location{}
-Blöcke im http{}
-Kontext den Wert von Anweisungen, die auf der http-
Ebene enthalten sind, und eine Anweisung in einem Server{}-
Block wird von allen darin enthaltenen untergeordneten Location{}-
Blöcken geerbt. Wenn jedoch dieselbe Direktive sowohl in einem übergeordneten Kontext als auch in seinem untergeordneten Kontext enthalten ist, werden die Werte nicht addiert. Stattdessen überschreibt der Wert im untergeordneten Kontext den übergeordneten Wert.
Der Fehler besteht darin, diese „Override-Regel“ für Array-Direktiven zu vergessen, die nicht nur in mehreren Kontexten, sondern auch mehrmals innerhalb eines bestimmten Kontexts enthalten sein können. Beispiele hierfür sind proxy_set_header
und add_header
. Wenn „add“ im Namen des zweiten Headers vorkommt, kann die Override-Regel besonders leicht vergessen werden.
Wir können anhand dieses Beispiels für add_header
veranschaulichen, wie Vererbung funktioniert:
http {
add_header X-HTTP-LEVEL-HEADER 1;
add_header X-ANOTHER-HTTP-LEVEL-HEADER 1;
server {
listen 8080;
location / {
return 200 "OK";
}
}
server {
listen 8081;
add_header X-SERVER-LEVEL-HEADER 1;
location / {
return 200 "OK";
}
location /test {
add_header X-LOCATION-LEVEL-HEADER 1;
return 200 "OK";
}
location /correct {
add_header X-HTTP-LEVEL-HEADER 1;
add_header X-ANOTHER-HTTP-LEVEL-HEADER 1;
add_header X-SERVER-LEVEL-HEADER 1;
add_header X-LOCATION-LEVEL-HEADER 1;
return 200 "OK";
}
}
}
Für den Server, der auf Port 8080 lauscht, gibt es weder im Server{}-
noch im Location{}
-Blöck eine Add_header-
Direktive. Die Vererbung ist also unkompliziert und wir sehen die beiden Header, die im http{}
-Kontext definiert sind:
% curl -i localhost:8080 HTTP/1.1 200 OK Server: nginx/1.21.5 Datum: Mo, 21. Februar 2022 10:12:15 GMT Inhaltstyp: Text/Plain Inhaltslänge: 2 Verbindung: Keep-Alive X-HTTP-LEVEL-HEADER: 1 X-EIN ANDERER-HTTP-LEVEL-HEADER: 1 Okay
Für den Server, der auf Port 8081 lauscht, gibt es eine add_header-
Direktive im Server{}-
Block, aber nicht in seinem untergeordneten Speicherort
/
Block. Der im Server{}-
Block definierte Header überschreibt die beiden im http{}
-Kontext definierten Header:
% curl -i localhost:8081 HTTP/1.1 200 OK Server: nginx/1.21.5 Datum: Mo, 21. Februar 2022 10:12:20 GMT Inhaltstyp: Text/Plain Inhaltslänge: 2 Verbindung: Keep-Alive X-SERVER-LEVEL-HEADER: 1 Okay
Im untergeordneten Standort-
/Testblock
gibt es eine add_header-
Direktive und diese überschreibt sowohl den Header aus dem übergeordneten Server{}-
Block als auch die beiden Header aus dem http{}
-Kontext:
% curl -i localhost:8081/test HTTP/1.1 200 OK Server: nginx/1.21.5 Datum: Mo, 21. Februar 2022 10:12:25 GMT Inhaltstyp: Text/Plain Inhaltslänge: 2 Verbindung: Keep-Alive X-LOCATION-LEVEL-HEADER: 1 Okay
Wenn wir möchten, dass ein location{}-
Block die in seinen übergeordneten Kontexten definierten Header zusammen mit allen lokal definierten Headern beibehält, müssen wir die übergeordneten Header innerhalb des location{}
-Blocks neu definieren. Das haben wir im Block „location
/correct“
getan:
% curl -i localhost:8081/korrektes HTTP/1.1 200 OK Server: nginx/1.21.5 Datum: Mo, 21. Februar 2022 10:12:30 GMT Inhaltstyp: Text/Plain Inhaltslänge: 2 Verbindung: Keep-Alive X-HTTP-LEVEL-HEADER: 1 X-EIN ANDERER-HTTP-LEVEL-HEADER: 1 X-SERVER-LEVEL-HEADER: 1 X-Standort-Ebene-Header: 1 Okay
Proxy_Buffering
Off-
DirektiveDie Proxy-Pufferung ist in NGINX standardmäßig aktiviert (die Direktive proxy_buffering
ist auf on
gesetzt). Proxy-Pufferung bedeutet, dass NGINX die Antwort eines Servers in internen Puffern speichert, sobald sie eingeht, und erst dann mit dem Senden von Daten an den Client beginnt, wenn die gesamte Antwort gepuffert ist. Durch das Puffern lässt sich die Leistung bei langsamen Clients optimieren. Da NGINX die Antwort so lange puffert, wie der Client zum Abrufen der gesamten Antwort benötigt, kann der Proxyserver seine Antwort so schnell wie möglich zurückgeben und wieder für die Bearbeitung anderer Anforderungen zur Verfügung stehen.
Wenn die Proxy-Pufferung deaktiviert ist, puffert NGINX nur den ersten Teil der Antwort eines Servers, bevor mit der Übermittlung an den Client begonnen wird, und zwar in einem Puffer, der standardmäßig eine Speicherseite groß ist (4 KB oder 8 KB , je nach Betriebssystem). Normalerweise ist das gerade genug Platz für den Antwortheader. NGINX sendet die Antwort dann synchron zum Empfang an den Client und zwingt den Server, im Leerlauf zu bleiben, während er wartet, bis NGINX das nächste Antwortsegment akzeptieren kann.
Daher sind wir überrascht, wie oft in Konfigurationen „Proxy_Buffering“
deaktiviert
ist . Vielleicht soll damit die für die Clients spürbare Latenzzeit verringert werden, doch der Effekt ist vernachlässigbar, während die Nebenwirkungen zahlreich sind: Wenn die Proxy-Pufferung deaktiviert ist, funktionieren Ratenbegrenzung und Caching nicht, auch wenn sie konfiguriert sind, die Leistung leidet usw.
Es gibt nur wenige Anwendungsfälle, in denen das Deaktivieren der Proxy-Pufferung sinnvoll sein kann (z. B. bei langem Polling). Daher raten wir dringend davon ab, die Standardeinstellung zu ändern. Weitere Informationen finden Sie im NGINX Plus-Administratorhandbuch .
if-
DirektiveDie if-
Direktive ist schwierig zu verwenden, insbesondere in location{}-
Blöcken. Es funktioniert oft nicht wie erwartet und kann sogar Segmentierungsfehler verursachen. Tatsächlich ist es so schwierig, dass es im NGINX-Wiki einen Artikel mit dem Titel „If is Evil“ gibt. Für eine ausführliche Erörterung der Probleme und ihrer Vermeidung verweisen wir Sie dorthin.
Im Allgemeinen sind return
und rewrite
die einzigen Anweisungen, die Sie innerhalb eines if{}-
Blocks immer sicher verwenden können. Im folgenden Beispiel wird if
verwendet, um Anforderungen zu erkennen, die den X‑Test-
Header enthalten (dies kann jedoch jede beliebige Bedingung sein, die Sie testen möchten). NGINX gibt die430
(
Anforderungsheaderfelder
zu
groß
)
-Fehler, fängt ihn am benannten Ort @error_430 ab und leitet die Anforderung an die Upstream-Gruppe mit dem Namen b weiter.
Standort / {
Fehlerseite 430 = @error_430;
wenn ($http_x_test) {
return 430;
}
Proxy-Pass http://a;
}
Standort @error_430 {
Proxy-Pass b;
}
Für diesen und viele andere Verwendungszwecke von if
ist es oft möglich, die Direktive vollständig zu vermeiden. Im folgenden Beispiel setzt der Block map{}
die Variable $upstream_name
auf b,
wenn die Anforderung den Header X‑Test
enthält, und die Anforderung wird an die Upstream-Gruppe mit diesem Namen weitergeleitet.
Karte $http_x_test $upstream_name {
Standard "b";
"" "a";
}
# ...
Standort / {
Proxy-Passwort http://$upstream_name;
}
Es ist durchaus üblich, mehrere virtuelle Server so zu konfigurieren, dass sie Anfragen an dieselbe Upstream-Gruppe weiterleiten (mit anderen Worten, die identische Proxy_pass-
Direktive in mehrere Server{}-
Blöcke aufzunehmen). Der Fehler in dieser Situation besteht darin, in jeden Server{}-
Block eine Health_check
-Direktive einzufügen. Dies führt lediglich zu einer stärkeren Belastung der Upstream-Server, ohne zusätzliche Informationen zu liefern.
Auf die Gefahr hin, dass es offensichtlich ist: Die Lösung besteht darin, nur eine Integritätsprüfung pro Upstream{}-
Block zu definieren. Hier definieren wir die Integritätsprüfung für die Upstream-Gruppe mit dem Namen „b“ an einem speziellen benannten Speicherort, komplett mit entsprechenden Timeouts und Header-Einstellungen.
Standort / {
proxy_set_header Host $host;
proxy_set_header "Verbindung" "";
proxy_http_version 1.1;
proxy_pass http://b;
}
Standort @health_check {
health_check;
proxy_connect_timeout 2s;
proxy_read_timeout 3s;
proxy_set_header Host example.com;
proxy_pass http://b;
}
In komplexen Konfigurationen kann die Verwaltung weiter vereinfacht werden, indem alle Integritätsprüfstandorte zusammen mit der NGINX Plus-API und dem Dashboard in einem einzigen virtuellen Server gruppiert werden, wie in diesem Beispiel.
server {
listen 8080;
location / {
# …
}
location @health_check_b {
health_check;
proxy_connect_timeout 2s;
proxy_read_timeout 3s;
proxy_set_header Host example.com;
proxy_pass http://b;
}
location @health_check_c {
health_check;
proxy_connect_timeout 2s;
proxy_read_timeout 3s;
proxy_set_header Host api.example.com;
proxy_pass http://c;
}
location /api {
api write=on;
# Anweisungen, die den Zugriff auf die API einschränken (siehe „Fehler 8“ weiter unten)
}
location = /dashboard.html {
root /usr/share/nginx/html;
}
}
Weitere Informationen zu Integritätsprüfungen für HTTP-, TCP-, UDP- und gRPC-Server finden Sie im NGINX Plus-Administratorhandbuch .
Grundlegende Kennzahlen zum NGINX-Betrieb sind im Stub-Status- Modul verfügbar. Für NGINX Plus können Sie mit der NGINX Plus-API auch einen viel umfangreicheren Satz von Metriken erfassen. Aktivieren Sie die Metrikerfassung, indem Sie die Direktive stub_status
bzw. api
in einen Server{}-
oder Location{}-
Block aufnehmen. Dieser wird zur URL, über die Sie dann die Metriken anzeigen. (Für die NGINX Plus-API müssen Sie auch gemeinsam genutzte Speicherzonen für die NGINX-Entitäten – virtuelle Server, Upstream-Gruppen, Caches usw. – konfigurieren, für die Sie Metriken erfassen möchten; siehe die Anweisungen im NGINX Plus-Administratorhandbuch .)
Einige der Kennzahlen enthalten vertrauliche Informationen, die für Angriffe auf Ihre Website oder die von NGINX geproxieden Apps verwendet werden können. Der Fehler, der uns manchmal in Benutzerkonfigurationen begegnet, liegt darin, dass der Zugriff auf die entsprechende URL nicht eingeschränkt wird. Hier sehen wir uns einige Möglichkeiten an, wie Sie die Metriken sichern können. Wir werden stub_status
in den ersten Beispielen verwenden.
Mit der folgenden Konfiguration kann jeder im Internet auf die Metriken unter http://example.com/basic_status zugreifen.
Server {
listen 80;
Servername example.com;
Standort = /basic_status {
stub_status;
}
}
Um die Metriken mit der HTTP-Basisauthentifizierung mit einem Kennwort zu schützen, schließen Sie die Anweisungen auth_basic
und auth_basic_user_file
ein. Die Datei (hier .htpasswd ) listet die Benutzernamen und Passwörter der Clients auf, die sich anmelden können, um die Metriken anzuzeigen:
Server {
listen 80;
Servername example.com;
Standort = /basic_status {
auth_basic „Site geschlossen“;
auth_basic_user_file conf.d/.htpasswd;
stub_status;
}
}
„allow“
und „deny“
Wenn Sie nicht möchten, dass sich autorisierte Benutzer anmelden müssen, und Sie die IP-Adressen kennen, von denen aus sie auf die Messdaten zugreifen, ist die Allow
-Direktive eine weitere Option. Sie können einzelne IPv4- und IPv6-Adressen und CIDR-Bereiche angeben. Die Direktive „Deny
All“
verhindert den Zugriff von allen anderen Adressen.
Server {
listen 80;
Servername example.com;
Standort = /basic_status {
192.168.1.0/24 zulassen;
10.1.1.0/16 zulassen;
2001:0db8::/32 zulassen;
96.1.2.23/32 zulassen;
alles verweigern;
Stub_status;
}
}
Was ist, wenn wir beide Methoden kombinieren möchten? Wir können Kunden den Zugriff auf die Messdaten von bestimmten Adressen ohne Kennwort gestatten und von Kunden mit anderen Adressen dennoch eine Anmeldung verlangen. Hierzu verwenden wir die Direktive „satisfy
any“
. Es weist NGINX an, Clients den Zugriff zu gestatten, die sich entweder mit HTTP Basic-Authentifizierungsdaten anmelden oder eine vorab genehmigte IP-Adresse verwenden. Für zusätzliche Sicherheit können Sie „Auf alle
erfüllen“
festlegen, um auch Personen mit bestimmten Adressen zur Anmeldung aufzufordern.
Server {
listen 80;
Servername monitor.example.com;
Standort = /basic_status {
alle Anforderungen erfüllen;
auth_basic „geschlossene Site“;
auth_basic_user_file conf.d/.htpasswd;
192.168.1.0/24 zulassen;
10.1.1.0/16 zulassen;
2001:0db8::/32 zulassen;
96.1.2.23/32 zulassen;
alle ablehnen;
stub_status;
}
}
Mit NGINX Plus verwenden Sie dieselben Techniken, um den Zugriff auf den NGINX Plus-API- Endpunkt ( http://monitor.example.com:8080/api/ im folgenden Beispiel) sowie auf das Dashboard zur Live-Aktivitätsüberwachung unter http://monitor.example.com/dashboard.html zu beschränken.
Diese Konfiguration erlaubt den Zugriff ohne Passwort nur für Clients aus dem Netzwerk 96.1.2.23/32 oder vom lokalen Host. Da die Anweisungen auf Serverebene
definiert werden, gelten für die API und das Dashboard dieselben Einschränkungen. Als Randbemerkung: Der Parameter „write=on“
für die API
bedeutet, dass diese Clients die API auch verwenden können, um Konfigurationsänderungen vorzunehmen.
Weitere Informationen zum Konfigurieren der API und des Dashboards finden Sie im NGINX Plus-Administratorhandbuch .
Server {
8080 abhören;
Servername monitor.example.com;
alle Anforderungen erfüllen;
auth_basic „geschlossene Site“;
auth_basic_user_file conf.d/.htpasswd;
127.0.0.1/32 zulassen;
96.1.2.23/32 zulassen;
alle verweigern;
Standort = /api/ {
api write=on;
}
Standort = /dashboard.html {
root /usr/share/nginx/html;
}
}
ip_hash
, wenn der gesamte Datenverkehr aus demselben /24 CIDR-Block stammtDer Algorithmus „ip_hash“
verteilt den Datenverkehr zwischen den Servern in einem Upstream{}-
Block, basierend auf einem Hash der Client-IP-Adresse. Der Hash-Schlüssel sind die ersten drei Oktette einer IPv4-Adresse oder die gesamte IPv6-Adresse. Die Methode stellt die Sitzungspersistenz her, was bedeutet, dass Anforderungen eines Clients immer an denselben Server weitergeleitet werden, es sei denn, der Server ist nicht verfügbar.
Angenommen, wir haben NGINX als Reverse-Proxy in einem für hohe Verfügbarkeit konfigurierten virtuellen privaten Netzwerk bereitgestellt. Wir platzieren verschiedene Firewalls, Router, Layer-4-Load Balancer und Gateways vor NGINX, um Datenverkehr aus verschiedenen Quellen (dem internen Netzwerk, Partnernetzwerken, dem Internet usw.) anzunehmen und ihn zur Reverse-Proxy-Weiterleitung an Upstream-Server an NGINX weiterzuleiten. Hier ist die anfängliche NGINX-Konfiguration:
http {
upstream {
ip_hash;
Server 10.10.20.105:8080;
Server 10.10.20.106:8080;
Server 10.10.20.108:8080;
}
Server {# …}
}
Es stellt sich jedoch heraus, dass es ein Problem gibt: Alle „abfangenden“ Geräte befinden sich im selben Netzwerk 10.10.0.0/24, sodass es für NGINX so aussieht, als käme der gesamte Datenverkehr von Adressen in diesem CIDR-Bereich. Denken Sie daran, dass der IP_Hash
-Algorithmus die ersten drei Oktette einer IPv4-Adresse hasht. In unserer Bereitstellung sind die ersten drei Oktette für jeden Client gleich – 10.10.0. Daher ist der Hash für alle derselbe und es gibt keine Grundlage für die Verteilung des Datenverkehrs auf verschiedene Server.
Die Lösung besteht darin, stattdessen den Hash
-Algorithmus mit der Variable $binary_remote_addr
als Hash-Schlüssel zu verwenden. Diese Variable erfasst die vollständige Clientadresse und wandelt sie in eine Binärdarstellung um, die 4 Bytes für eine IPv4-Adresse und 16 Bytes für eine IPv6-Adresse umfasst. Jetzt ist der Hash für jedes abfangende Gerät unterschiedlich und der Lastausgleich funktioniert wie erwartet.
Wir schließen auch den konsistenten
Parameter ein, um die Ketama- Hashing-Methode anstelle der Standardmethode zu verwenden. Dadurch wird die Anzahl der Schlüssel, die bei einer Änderung des Serversatzes einem anderen Upstream-Server neu zugeordnet werden, erheblich reduziert, was zu einer höheren Cache-Trefferquote für Caching-Server führt.
http {
upstream {
Hash $binary_remote_addr konsistent;
Server 10.10.20.105:8080;
Server 10.10.20.106:8080;
Server 10.10.20.108:8080;
}
Server {# …}
}
Angenommen, Sie verwenden NGINX für einen der einfachsten Anwendungsfälle, nämlich als Reverse-Proxy für eine einzelne NodeJS-basierte Back-End-Anwendung, die auf Port 3000 lauscht. Eine typische Konfiguration könnte folgendermaßen aussehen:
http {
Server {
Listen 80;
Servername example.com;
Standort / {
Proxy_Set_Header Host $host;
Proxy_Pass http://localhost:3000/;
}
}
}
Unkompliziert, oder? Die Proxy_Pass-
Direktive teilt NGINX mit, wohin Anfragen von Clients gesendet werden sollen. NGINX muss lediglich den Hostnamen in eine IPv4- oder IPv6-Adresse auflösen. Sobald die Verbindung hergestellt ist, leitet NGINX Anfragen an diesen Server weiter.
Der Fehler besteht hier in der Annahme, dass die Erstellung eines Upstream{}-
Blocks sinnlos sei, weil es nur einen Server gebe und somit kein Grund bestehe, die Lastverteilung zu konfigurieren. Tatsächlich schaltet ein Upstream{}-
Block mehrere Funktionen frei, die die Leistung verbessern, wie diese Konfiguration zeigt:
http {
Upstream node_backend {
Zone Upstreams 64K;
Server 127.0.0.1:3000 max_fails=1 fail_timeout=2s;
Keepalive 2;
}
Server {
Listen 80;
Servername example.com;
Standort / {
Proxy_Set_Header Host $host;
Proxy_Pass http://node_backend/;
Proxy_next_upstream Fehler Timeout http_500;
}
}
}
Die Zonendirektive
richtet eine gemeinsam genutzte Speicherzone ein, in der alle NGINX-Arbeitsprozesse auf dem Host auf Konfigurations- und Statusinformationen zu den Upstream-Servern zugreifen können. Mehrere Upstream-Gruppen können die Zone gemeinsam nutzen. Mit NGINX Plus ermöglicht Ihnen die Zone außerdem, die NGINX Plus-API zu verwenden, um die Server in einer Upstream-Gruppe und die Einstellungen für einzelne Server zu ändern, ohne NGINX neu starten zu müssen. Weitere Einzelheiten finden Sie im NGINX Plus-Administratorhandbuch .
Die Serverdirektive
verfügt über mehrere Parameter, mit denen Sie das Serververhalten optimieren können. In diesem Beispiel haben wir die Bedingungen geändert, die NGINX verwendet, um zu bestimmen, dass ein Server fehlerhaft ist und daher keine Anfragen annehmen kann. Dabei wird ein Server als fehlerhaft betrachtet, wenn ein Kommunikationsversuch auch nur einmal innerhalb eines Zeitraums von 2 Sekunden fehlschlägt (anstatt wie standardmäßig einmal in einem Zeitraum von 10 Sekunden ).
Wir kombinieren diese Einstellung mit der Direktive „proxy_next_upstream“
, um zu konfigurieren, was NGINX als fehlgeschlagenen Kommunikationsversuch betrachtet. In diesem Fall leitet es Anfragen an den nächsten Server in der Upstream-Gruppe weiter. Zu den Standardfehler- und Timeoutbedingungen fügen wir http_500
hinzu, damit NGINX ein HTTP berücksichtigt 500
(Interner
Serverfehler
)
-Code von einem Upstream-Server, der einen fehlgeschlagenen Versuch darstellt.
Die Keepalive-
Direktive legt die Anzahl der inaktiven Keepalive-Verbindungen zu Upstream-Servern fest, die im Cache jedes Arbeitsprozesses gespeichert werden. Die Vorteile haben wir bereits bei Fehler 3 besprochen: Keepalive-Verbindungen zu Upstream-Servern werden nicht aktiviert .
Mit NGINX Plus können Sie zusätzliche Funktionen mit Upstream-Gruppen konfigurieren:
Wir haben oben erwähnt, dass NGINX Open Source Server-Hostnamen nur einmal, beim Start, in IP-Adressen auflöst. Der Resolve-
Parameter der Serverdirektive ermöglicht es NGINX Plus, Änderungen an den IP-Adressen zu überwachen, die dem Domänennamen eines Upstream-Servers entsprechen, und die Upstream-Konfiguration automatisch zu ändern, ohne dass ein Neustart erforderlich ist.
Der Serviceparameter
ermöglicht NGINX Plus außerdem, DNS- SRV-
Einträge zu verwenden, die Informationen zu Portnummern, Gewichten und Prioritäten enthalten. Dies ist in Microservices-Umgebungen von entscheidender Bedeutung, in denen die Portnummern der Dienste häufig dynamisch zugewiesen werden.
Weitere Informationen zum Auflösen von Serveradressen finden Sie unter „Verwenden von DNS für die Diensterkennung mit NGINX und NGINX Plus“ in unserem Blog.
Der Parameter „slow_start“
der Serverdirektive ermöglicht es NGINX Plus, die Anzahl der Anfragen, die es an einen Server sendet, der nun als fehlerfrei und zum Annehmen von Anfragen verfügbar gilt, schrittweise zu erhöhen. Dadurch wird eine plötzliche Flut von Anfragen verhindert, die den Server überfordern und zu einem erneuten Ausfall führen könnte.
Die Warteschlangendirektive
ermöglicht es NGINX Plus, Anfragen in eine Warteschlange zu stellen, wenn es nicht möglich ist, einen Upstream-Server zur Bearbeitung der Anfrage auszuwählen, anstatt sofort einen Fehler an den Client zurückzugeben.
Um NGINX Plus auszuprobieren, starten Sie noch heute Ihre kostenlose 30-Tage-Testversion oder kontaktieren Sie uns, um Ihre Anwendungsfälle zu besprechen .
„Dieser Blogbeitrag kann auf Produkte verweisen, die nicht mehr verfügbar und/oder nicht mehr unterstützt werden. Die aktuellsten Informationen zu verfügbaren F5 NGINX-Produkten und -Lösungen finden Sie in unserer NGINX-Produktfamilie . NGINX ist jetzt Teil von F5. Alle vorherigen NGINX.com-Links werden auf ähnliche NGINX-Inhalte auf F5.com umgeleitet."