Nginx Performance-Tuning: Worker-Prozesse und Verbindungen optimieren
Optimieren Sie Nginx-Worker-Prozesse, Worker-Verbindungen, Dateilimits, Keepalive-Verhalten und Upstream-Kapazitäten ohne Rätselraten.
Nginx Performance-Tuning: Worker-Prozesse und Verbindungen optimieren
Nginx Performance-Tuning beginnt oft mit zwei Einstellungen: Worker-Prozesse und Worker-Verbindungen. Diese Einstellungen bestimmen, wie viele Anfragen Ihr Server gleichzeitig verarbeiten kann, sodass kleine Fehler bei Traffic-Spitzen als langsame Seiten, stockende Downloads oder Verbindungsfehler auftreten können.
Die gute Nachricht ist, dass Sie nicht wild raten müssen. Sie können Nginx optimieren, indem Sie sein Worker-Modell an Ihre CPU, Dateilimits, Traffic-Muster und das Verhalten der Upstream-Anwendung anpassen.
Wie Nginx-Worker Traffic verarbeiten
Nginx verwendet einen Master-Prozess und einen oder mehrere Worker-Prozesse. Der Master-Prozess liest die Konfiguration, startet Worker und führt Neuladungen durch. Die Worker erledigen die eigentliche Anfrageverarbeitung.
Jeder Worker kann viele Verbindungen verwalten, da Nginx ein ereignisgesteuertes Modell verwendet. Das unterscheidet sich von älteren Webservern, die oft einen Prozess oder Thread pro Anfrage benötigten. Ein Nginx-Worker kann Tausende von Keepalive-Verbindungen im Leerlauf offen halten, wenn das Betriebssystem dies zulässt.
Die beiden Kern-Direktiven befinden sich normalerweise in /etc/nginx/nginx.conf:
worker_processes auto;
events {
worker_connections 1024;
}
worker_processes auto; weist Nginx an, für jeden verfügbaren CPU-Kern einen Worker zu erstellen. Für die meisten modernen Linux-Server ist dies der richtige Ausgangspunkt. Es vermeidet das Festcodieren eines Werts, der falsch wird, wenn Sie eine virtuelle Maschine vergrößern oder verkleinern.
worker_connections legt die maximale Anzahl gleichzeitiger Verbindungen fest, die jeder Worker öffnen kann. Die grobe Obergrenze ist:
worker_processes * worker_connections
Wenn Sie 4 Worker und 4096 Worker-Verbindungen haben, beträgt das theoretische Maximum 16.384 Verbindungen. Im realen Leben ist die nutzbare Anzahl geringer, da Reverse-Proxy-Traffic sowohl Client-seitige als auch Upstream-Verbindungen nutzen kann.
Wenn Nginx beispielsweise Traffic an eine Node.js-App weiterleitet, kann eine Benutzeranfrage eine Client-Verbindung plus eine Upstream-Verbindung verbrauchen. Das bedeutet, dass 16.384 offene Verbindungen je nach Keepalive und Anfrage-Timing näher an 8.000 aktive Proxy-Anfragen unterstützen könnten.
Auswahl von Worker-Prozess- und Verbindungswerten
Beginnen Sie mit worker_processes auto, es sei denn, Sie haben einen bestimmten Grund dagegen. Das manuelle Setzen dieses Werts über die CPU-Anzahl hinaus hilft selten. Es kann den Kontextwechsel erhöhen und die Leistung unter Last verschlechtern.
Stimmen Sie dann worker_connections basierend auf der erwarteten Parallelität ab. Ein ruhiges internes Tool kann mit 1024 auskommen. Eine öffentliche Website hinter einem Load Balancer benötigt möglicherweise 4096, 8192 oder mehr.
Eine praktische Basislinie für viele Produktionsserver sieht so aus:
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
multi_accept on;
}
worker_rlimit_nofile erhöht das Dateideskriptor-Limit, das Nginx-Workern zur Verfügung steht. Dies ist wichtig, da jeder Netzwerk-Socket einen Dateideskriptor verwendet. Wenn das Betriebssystem-Limit niedrig bleibt, hilft eine Erhöhung von worker_connections allein nicht.
Sie sollten auch das Service-Manager-Limit überprüfen. Auf systemd-Systemen benötigt Nginx möglicherweise einen Override wie:
[Service]
LimitNOFILE=65535
Nachdem Sie die systemd-Limits geändert haben, laden Sie systemd neu und starten Sie Nginx neu. Eine breitere Befehlsreferenz finden Sie unter Nginx-Service-Steuerungsbefehle.
Seien Sie vorsichtig mit multi_accept on. Es erlaubt einem Worker, nach Erhalt einer Bereitschaftsbenachrichtigung so viele neue Verbindungen wie möglich anzunehmen. Dies kann bei Bursts helfen, ist aber kein Wundermittel. Wenn Ihre Upstream-App langsam ist, kann das schnellere Annehmen von Verbindungen die Warteschlangen nur schneller füllen.
Betriebssystem-Limits, die Nginx beeinflussen
Nginx-Einstellungen sitzen auf Linux-Limits. Wenn diese Limits zu klein sind, stößt Nginx an eine Obergrenze, selbst wenn seine eigene Konfiguration großzügig aussieht.
Überprüfen Sie beim Tuning diese Bereiche:
- Offenes Dateilimit für den Nginx-Prozess
- Kernel-Netzwerk-Backlog-Einstellungen
- Ephemerale Port-Verfügbarkeit für starken Proxy-Traffic
- Upstream-Keepalive-Verhalten
- Leerlauf-Timeout-Werte des Load Balancers
Das offene Dateilimit ist der häufigste Engpass. Wenn Nginx Meldungen wie worker_connections are not enough oder too many open files protokolliert, müssen Sie sowohl die Nginx- als auch die systemd-Limits überprüfen.
Backlog-Einstellungen sind wichtig, wenn viele Clients gleichzeitig eine Verbindung herstellen. Wenn die Kernel-Accept-Queue voll wird, können Benutzer Verbindungs-Timeouts sehen, obwohl die CPU-Auslastung normal aussieht. Werte wie net.core.somaxconn und net.ipv4.tcp_max_syn_backlog werden oft bei Hochverkehrs-Tuning überprüft.
Kopieren Sie keine großen Kernel-Werte aus zufälligen Beispielen, ohne sie zu testen. Ein kleines Team, das einen API-Server betreibt, benötigt nicht die gleichen Einstellungen wie ein CDN-Edge-Node. Tunen Sie in Schritten, messen Sie und machen Sie sich Notizen.
Es gibt ein weiteres Detail, das Leute verwirrt: Das Nginx-Verbindungslimit ist nicht das einzige Verbindungslimit im Pfad. Ein Cloud-Load-Balancer hat Leerlauf-Timeouts. Eine Container-Laufzeitumgebung kann Network Address Translation-Limits haben. Die Backend-App kann ihren eigenen Worker-Pool oder Datenbank-Verbindungspool haben. Wenn Nginx 20.000 Verbindungen akzeptieren kann, die App aber nur 200 gleichzeitige Anfragen verarbeiten kann, werden Benutzer trotzdem warten.
Aus diesem Grund sollte eine Verbindungsoptimierungsänderung eine schnelle End-to-End-Überprüfung beinhalten. Führen Sie einen kleinen Lasttest von einem Host außerhalb des Servers durch, beobachten Sie die aktiven Nginx-Verbindungen und beobachten Sie auch das Backend. Wenn die Backend-Latenz stark ansteigt, während Nginx ruhig bleibt, erfüllt der Proxy seine Aufgabe und das nächste Limit liegt dahinter.
Tuning für Reverse-Proxy-Workloads
Viele Nginx-Server fungieren als Reverse-Proxys vor Anwendungsservern. In dieser Rolle ist das Upstream-Verhalten genauso wichtig wie die Nginx-Kapazität.
Verwenden Sie Upstream-Keepalive, wenn Nginx wiederholt mit demselben Backend-Pool spricht:
upstream app_backend {
server 127.0.0.1:3000;
keepalive 32;
}
server {
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://app_backend;
}
}
Dies reduziert die Kosten für das Öffnen neuer Backend-Verbindungen. Es ist besonders nützlich, wenn Ihre App viele kleine Anfragen erhält, wie z. B. API-Aufrufe von einem Dashboard.
Überprüfen Sie auch Ihre Timeout-Werte. Sehr lange Proxy-Timeouts können Worker-Verbindungen blockieren, nachdem Clients verschwunden sind oder Anwendungen nicht mehr reagieren. Sehr kurze Timeouts können legitime langsame Anfragen unterbrechen. Passen Sie die Timeout-Werte an die Arbeitslast an, anstatt überall einen Standardwert zu verwenden.
Ein praktisches Szenario: Ihre Website ist die meiste Zeit des Tages schnell, verlangsamt sich jedoch während eines Newsletter-Versands. Die CPU-Auslastung beträgt nur 35 %, aber Nginx-Protokolle zeigen Verbindungswarnungen. Das deutet weg von der reinen CPU hin zu Verbindungslimits, Dateideskriptoren oder Upstream-Warteschlangen. Eine Erhöhung der Worker-Verbindungen kann helfen, aber nur, wenn die App und das Betriebssystem die zusätzliche Last unterstützen können.
Ein weiteres häufiges Szenario ist eine Dashboard-App, die viele kleine API-Aufrufe von jedem Browser-Tab aus tätigt. Zehn Personen können Hunderte von kurzen Anfragen erstellen. In diesem Fall ist Upstream-Keepalive oft wichtiger als die bloße Erhöhung von worker_connections, da der wiederholte TCP-Aufbau zum Backend unnötiger Overhead wird.
Für einen Datei-Download-Dienst ist die Geschichte anders. Eine kleine Anzahl von Benutzern kann Verbindungen für lange Zeit offen halten, während sie große Dateien herunterladen. Möglicherweise benötigen Sie genügend Worker-Verbindungen für langlebige Übertragungen, aber Sie sollten auch sendfile, Datenträgerdurchsatz, Netzwerkdurchsatz und Client-Timeout-Verhalten überprüfen.
Für WebSocket- oder Long-Polling-Apps sind Leerlaufverbindungen normal. Eine hohe Waiting-Zahl ist nicht automatisch schlecht. Die Frage ist, ob diese Leerlaufverbindungen genügend Kapazität für neue Anfragen lassen und ob die Speichernutzung vorhersagbar bleibt.
Lesen von stub_status während des Tunings
Das stub_status-Modul bietet Ihnen eine schnelle Ansicht des Verbindungsverhaltens:
Active connections: 291
server accepts handled requests
1162447 1162447 4496426
Reading: 6 Writing: 17 Waiting: 268
Reading bedeutet, dass Nginx Anfrage-Header liest. Eine anhaltend hohe Zahl kann auf langsame Clients, große Header oder ein Angriffsmuster hinweisen. Writing bedeutet, dass Nginx Antworten sendet. Dies kann ansteigen, wenn Clients langsam Daten empfangen oder wenn Antworten groß sind. Waiting bedeutet Keepalive-Verbindungen im Leerlauf. Diese Zahl kann auf gesunden Websites hoch sein.
Die Zähler accepts und handled sollten sich normalerweise gemeinsam bewegen. Wenn die akzeptierten Verbindungen steigen, aber die bearbeiteten Verbindungen hinterherhinken oder Fehler auftreten, überprüfen Sie die Worker-Limits und Dateideskriptor-Limits. Überprüfen Sie auch, ob der Kernel Verbindungen verwirft, bevor Nginx sie verarbeiten kann.
Diese Zähler sind einfach, aber sie sind nützlich, weil sie Verbindungsdruck vom CPU-Druck trennen. Wenn die aktiven Verbindungen niedrig und die CPU hoch ist, liegt das Problem wahrscheinlich nicht bei worker_connections. Wenn die aktiven Verbindungen hoch und die CPU niedrig ist, werden Verbindungslimits, Keepalive-Verhalten, Upstream-Warteschlangen oder langsame Clients wahrscheinlicher.
Eine sichere Basiskonfiguration
Für einen kleinen Produktionsserver würde ich lieber konservativ beginnen und messen:
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
multi_accept on;
}
http {
keepalive_timeout 30s;
keepalive_requests 1000;
}
Dies ist keine universelle beste Konfiguration. Es ist ein vernünftiger Ausgangspunkt für viele normale Reverse-Proxy-Workloads. Eine sehr kleine VM benötigt möglicherweise weniger. Ein vielbeschäftigter Edge-Proxy benötigt möglicherweise viel mehr. Der wichtige Teil ist, dass worker_connections und worker_rlimit_nofile aufeinander abgestimmt sind.
Vergleichen Sie nach dem Anwenden einer Basislinie die Metriken vorher und nachher bei ähnlichem Traffic. Beurteilen Sie eine Tuning-Änderung nicht nach einer glücklichen Minute nach dem Neuladen. Betrachten Sie die p95- oder p99-Latenz, Fehlerrate, CPU, Speicher und Backend-Warteschlangen über genügend Zeit, um das tatsächliche Verhalten zu sehen.
Fehler, die Verbindungs-Tuning zufällig erscheinen lassen
Der erste Fehler ist das Zählen von Anfragen anstelle von Verbindungen. Ein Browser kann eine Verbindung für mehrere Anfragen wiederverwenden, und HTTP/2 kann viele Anfragen über eine Verbindung multiplexen. Ein langsamer Client kann auch eine Verbindung offen halten, während er sehr wenig nützliche Arbeit verrichtet. Das bedeutet, dass "wir nur 500 Anfragen pro Sekunde erhalten" Ihnen nicht sagt, wie viele Verbindungen Nginx benötigt.
Der zweite Fehler ist das Vergessen von Upstream-Verbindungen. Wenn Nginx statische Dateien bereitstellt, sind die meisten Verbindungen clientseitig. Wenn Nginx als Proxy für eine App fungiert, benötigen aktive Anfragen oft auch Backend-Sockets. Wenn Sie Keepalive zum Upstream verwenden, bleiben einige Backend-Verbindungen zur Wiederverwendung offen. Das ist gut, verbraucht aber trotzdem Dateideskriptoren auf beiden Seiten.
Der dritte Fehler ist das Erhöhen von Nginx-Limits ohne Überprüfung der Anwendung. Angenommen, Nginx kann jetzt 12.000 gleichzeitige Verbindungen akzeptieren, aber die Anwendung hat 16 Worker-Prozesse und einen Datenbank-Pool von 50 Verbindungen. Nginx wird mehr Arbeit annehmen, als die App erledigen kann. Benutzer sehen möglicherweise weniger sofortige Verbindungsfehler, aber die Latenz kann sich verschlechtern, weil Anfragen länger in Warteschlangen warten.
Der vierte Fehler ist die Verwendung langer Keepalive-Timeouts überall. Keepalive ist nützlich, weil es wiederholten TCP- und TLS-Aufbau vermeidet. Aber ein sehr langes Timeout kann nach einem Traffic-Spike viele Leerlauf-Sockets offen lassen. Auf einem speicherreichen Edge-Proxy mag das in Ordnung sein. Auf einer kleinen VM kann es aktive Arbeit verdrängen. Wenn Sie eine große Waiting-Anzahl und eine geringe Anfrage-Wiederverwendung sehen, versuchen Sie ein kürzeres keepalive_timeout und messen Sie erneut.
Fehlerbehebungsbeispiele
Wenn das Fehlerprotokoll worker_connections are not enough anzeigt, überprüfen Sie den konfigurierten Wert, die Anzahl der Worker und das Prozess-Dateilimit:
grep -R "worker_connections\\|worker_processes\\|worker_rlimit_nofile" /etc/nginx/nginx.conf /etc/nginx/conf.d
cat /proc/$(pgrep -o nginx)/limits | grep "open files"
Der Befehl pgrep -o nginx findet normalerweise den ältesten Nginx-Prozess, der oft der Master ist. Auf einigen Systemen bevorzugen Sie vielleicht systemctl status nginx, um die Haupt-PID zu sehen.
Wenn das Fehlerprotokoll too many open files anzeigt, erhöhen Sie nicht nur worker_connections. Der Prozess erreicht sein Deskriptor-Limit. Fügen Sie LimitNOFILE für den systemd-Dienst hinzu oder passen Sie es an, laden Sie systemd neu und starten Sie Nginx neu, damit das neue Limit tatsächlich angewendet wird:
sudo systemctl edit nginx
sudo systemctl daemon-reload
sudo systemctl restart nginx
Wenn Benutzer Timeouts sehen, aber Nginx freie CPU und keine Verbindungswarnungen hat, suchen Sie hinter Nginx. Überprüfen Sie die Upstream-Antwortzeit in den Zugriffsprotokollen. Überprüfen Sie den App-Worker-Pool. Überprüfen Sie Datenbankverbindungen. Ein Reverse-Proxy kann Traffic reibungslos annehmen, während der eigentliche Engpass ein gesättigtes Backend ist.
Wenn ein Spike zu Verbindungszurücksetzungen führt, bevor Anfragen in den Zugriffsprotokollen erscheinen, liegt das Problem möglicherweise vor der Nginx-Anfrageverarbeitung. Überprüfen Sie die Kernel-Backlog-Einstellungen, Load-Balancer-Protokolle, Firewall-Status-Tabellen und SYN-Flood-Schutz. Nginx kann eine Anfrage, die es nie erhalten hat, nicht protokollieren.
So testen Sie Änderungen sicher
Optimieren Sie niemals die Produktion, indem Sie bearbeiten und hoffen. Testen Sie zuerst die Syntax:
sudo nginx -t
Laden Sie dann Nginx neu, damit aktive Verbindungen ordnungsgemäß behandelt werden:
sudo systemctl reload nginx
Beobachten Sie nach jeder Änderung das Fehlerprotokoll:
sudo tail -f /var/log/nginx/error.log
Sie sollten auch die Anfragelatenz, 4xx- und 5xx-Raten, aktive Verbindungen, CPU, Speicher und Upstream-Antwortzeit überwachen. Eine Tuning-Änderung, die die Verbindungskapazität erhöht, aber die Anwendungslatenz erhöht, ist möglicherweise kein echter Gewinn.
Für tiefere Validierungsschritte siehe Testen von Nginx-Konfigurationen.
Wann Sie einen Spezialisten hinzuziehen sollten
Rufen Sie einen erfahrenen DevOps-Ingenieur oder Webspezialisten für Leistungsoptimierung, wenn Nginx-Fehler nach dem grundlegenden Tuning fortbestehen, wenn Traffic-Spitzen den Umsatz beeinträchtigen oder wenn Sie Kernel-Netzwerkeinstellungen auf einem Produktionssystem ändern. Gleiches gilt, wenn Sie Nginx vor Zahlungsabläufen, Anmeldesystemen oder kritischen APIs optimieren.
Professionelle Hilfe ist auch nützlich, wenn der Engpass unklar ist. Nginx mag wie das Problem aussehen, wenn das eigentliche Problem eine langsame Datenbank, ein erschöpfter Upstream-App-Pool, eine überlastete TLS-Terminierungsschicht oder ein Load-Balancer-Timeout-Konflikt ist.
Die wichtigste Erkenntnis ist einfach: Stimmen Sie Worker-Prozesse auf die CPU ab, stimmen Sie Worker-Verbindungen auf die Parallelität ab und stellen Sie sicher, dass die Linux-Dateilimits beide unterstützen. Ändern Sie jeweils eine Ebene, testen Sie die Konfiguration vor dem Neuladen und messen Sie echten Traffic, anstatt theoretischen Maximalwerten zu vertrauen.