„Wenn #nginx nicht vor deinem Node-Server sitzt, machst du wahrscheinlich etwas falsch.“ – Bryan Hughes auf Twitter
Node.js ist das führende Tool zur Erstellung von Serveranwendungen in JavaScript, der weltweit beliebtesten Programmiersprache. Da Node.js sowohl die Funktionen eines Webservers als auch die eines Anwendungsservers bietet, gilt es heute als wichtiges Tool für die Entwicklung und Bereitstellung verschiedenster Anwendungen auf Microservices-Basis. (Laden Sie kostenlos einen Forrester-Bericht über Node.js und NGINX herunter.)
Node.js kann Java oder .NET bei der Entwicklung von Backend-Anwendungen ersetzen oder ergänzen.
Node.js ist Single-Threaded und verwendet nicht blockierende E/A, wodurch es skalierbar ist und Zehntausende gleichzeitiger Vorgänge unterstützen kann. Es weist dieselben Architekturmerkmale wie NGINX auf und löst das C10K-Problem – die Unterstützung von mehr als 10.000 gleichzeitigen Verbindungen –, zu dessen Lösung auch NGINX entwickelt wurde. Node.js ist für seine hohe Leistung und Entwicklerproduktivität bekannt.
Was könnte da schon schiefgehen?
Node.js weist einige Schwachstellen und Sicherheitslücken auf, die bei Node.js-basierten Systemen zu Leistungseinbußen oder sogar Abstürzen führen können. Probleme treten häufiger auf, wenn eine Node.js-basierte Webanwendung einen rasanten Anstieg des Datenverkehrs verzeichnet.
Außerdem ist Node.js ein hervorragendes Tool zum Erstellen und Ausführen von Anwendungslogik, die die zentralen, dynamischen Inhalte Ihrer Webseite erzeugt. Für die Bereitstellung statischer Inhalte – beispielsweise Bilder und JavaScript-Dateien – oder die Lastverteilung auf mehrere Server ist es jedoch weniger gut geeignet.
Um Node.js optimal zu nutzen, müssen Sie statische Inhalte zwischenspeichern, Proxy- und Lastverteilungsfunktionen für mehrere Anwendungsserver bereitstellen und Portkonflikte zwischen Clients, Node.js und Hilfsdiensten wie Servern, auf denen Socket.IO ausgeführt wird, verwalten. NGINX eignet sich für all diese Aufgaben und ist damit ein hervorragendes Werkzeug zur Leistungsoptimierung von Node.js.
Nutzen Sie diese Tipps, um die Leistung von Node.js-Anwendungen zu verbessern:
- Implementieren Sie einen Reverse-Proxy-Server
- Statische Dateien zwischenspeichern
- Datenverkehr auf mehrere Server verteilen
- WebSocket-Verbindungen über einen Proxy weiterleiten
- SSL/TLS und HTTP/2 implementieren
Hinweis: Eine schnelle Möglichkeit, die Leistung von Node.js-Anwendungen zu verbessern, besteht darin, Ihre Node.js-Konfiguration so anzupassen, dass moderne Mehrkernserver optimal genutzt werden. Lesen Sie dazu die Node.js-Dokumentation, um zu erfahren, wie Sie Node.js für jeden Prozessor Ihres Webservers einen separaten untergeordneten Prozess erzeugen lassen. Jeder Prozess wird dann wie von Zauberhand genau einem der Prozessoren zugewiesen, was die Leistung erheblich steigert.
Tipp 1 – Implementieren Sie einen Reverse-Proxy-Server
Wir bei NGINX, Inc. sind immer ein wenig entsetzt, wenn wir sehen, dass Anwendungsserver, die das Herzstück hochperformanter Websites bilden, direkt dem eingehenden Internetverkehr ausgesetzt sind. Dazu gehören beispielsweise viele WordPress-basierte Websites sowie Node.js-Websites.
Node.js ist stärker als die meisten Anwendungsserver auf Skalierbarkeit ausgelegt, und seine Webserver-Komponente kann ein hohes Internet-Datenverkehrsaufkommen recht gut bewältigen. Doch die Bereitstellung von Webinhalten ist nicht die eigentliche Daseinsberechtigung von Node.js – dafür wurde es nicht wirklich entwickelt.
Wenn Sie eine stark frequentierte Website betreiben, besteht der erste Schritt zur Steigerung der Anwendungsleistung darin, Ihrem Node.js-Server einen Reverse-Proxy-Server vorzuschalten. Dadurch wird der Node.js-Server vor dem direkten Internetdatenverkehr geschützt, und Sie erhalten große Flexibilität beim Einsatz mehrerer Anwendungsserver, bei der Lastverteilung auf die Server und beim Zwischenspeichern von Inhalten.

NGINX als Reverse-Proxy-Server vor eine bestehende Serverkonfiguration zu schalten und anschließend für weitere Zwecke einzusetzen, ist ein zentraler Anwendungsfall für NGINX, der von mehreren zehn Millionen Websites weltweit umgesetzt wird.
Die Verwendung von NGINX als Reverse-Proxy-Server für Node.js bietet unter anderem folgende Vorteile:
- Vereinfachung der Verwaltung von Berechtigungen und der Portzuweisungen
- Statische Bilder effizienter bereitstellen (siehe nächster Tipp)
- Node.js-Abstürze erfolgreich bewältigen
- DoS-Angriffe abwehren
Hinweis: In diesen Tutorials wird erklärt, wie NGINX als Reverse-Proxy-Server in Ubuntu 14.04- oder CentOS-Umgebungen eingesetzt wird. Sie bieten einen nützlichen Überblick für alle, die NGINX vor Node.js schalten möchten.
Tipp 2 – Statische Dateien zwischenspeichern
Mit zunehmender Nutzung einer Node.js-basierten Website gerät der Server allmählich an seine Belastungsgrenze. An diesem Punkt sollten Sie zwei Dinge tun:
- Holen Sie das Beste aus dem Node.js-Server heraus
- Das Hinzufügen von Anwendungsservern und die Lastverteilung zwischen ihnen vereinfachen
Das ist tatsächlich ganz einfach. Implementieren Sie zunächst NGINX als Reverse-Proxy-Server, wie im vorherigen Tipp beschrieben. Dadurch lassen sich Caching, Lastverteilung (wenn Sie mehrere Node.js-Server betreiben) und weitere Funktionen problemlos umsetzen.
Auf der Website von Modulus, einer Plattform für Anwendungscontainer, finden Sie einen hilfreichen Artikel darüber, wie sich die Leistung von Node.js-Anwendungen mit NGINX erheblich steigern lässt. Als Node.js die gesamte Arbeit allein erledigte, konnte die Website des Autors durchschnittlich knapp 900 Anfragen pro Sekunde verarbeiten. Mit NGINX als Reverse-Proxy-Server, der statische Inhalte bereitstellte, verarbeitete dieselbe Website mehr als 1600 Anfragen pro Sekunde – eine Leistungssteigerung um nahezu das Doppelte.
Durch die Verdopplung der Leistung gewinnen Sie Zeit, um weitere Maßnahmen zur Bewältigung des künftigen Wachstums zu ergreifen. Dazu gehören etwa die Überprüfung (und gegebenenfalls Verbesserung) Ihres Website-Designs, die Optimierung Ihres Anwendungscodes und die Bereitstellung zusätzlicher Anwendungsserver.
Im Folgenden finden Sie den Konfigurationscode für eine auf Modulus betriebene Website:
server { listen 80;
server_name static-test-47242.onmodulus.net;
root /mnt/app;
index index.html index.htm;
location /static/ {
try_files $uri $uri/ =404;
}
location /api/ {
proxy_pass http://node-test-45750.onmodulus.net;
}
}In diesem ausführlichen Artikel erklärt Patrick Nommensen von NGINX, Inc., wie er statische Inhalte seines persönlichen Blogs zwischenspeichert, der auf der Open-Source-Blogging-Plattform Ghost, einer Node.js-Anwendung, läuft. Obwohl einige Details speziell auf Ghost zugeschnitten sind, lässt sich ein Großteil des Codes auch für andere Node.js-Anwendungen verwenden.
Beispielsweise möchten Sie im NGINX-location-Block wahrscheinlich bestimmte Inhalte vom Caching ausschließen. Die Administrationsoberfläche einer Blogging-Plattform sollte in der Regel nicht zwischengespeichert werden. Mit dem folgenden Konfigurationscode wird das Caching der Ghost-Administrationsoberfläche deaktiviert bzw. ausgeschlossen:
location ~ ^/(?:ghost|signout) { proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://ghost_upstream;
add_header Cache-Control "no-cache, private, no-store,
must-revalidate, max-stale=0, post-check=0, pre-check=0";
}Allgemeine Informationen zur Bereitstellung statischer Inhalte finden Sie im NGINX Plus-Administratorhandbuch. Das Administratorhandbuch enthält Konfigurationsanweisungen, verschiedene Optionen für die Reaktion auf erfolgreiche oder fehlgeschlagene Versuche, eine Datei zu finden, sowie Optimierungsansätze für eine noch höhere Leistung.
Das Zwischenspeichern statischer Dateien auf dem NGINX-Server entlastet den Node.js-Anwendungsserver erheblich und ermöglicht so eine deutlich höhere Leistung.
Tipp 3 – Implementieren Sie einen Node.js-Load-Balancer
Der eigentliche Schlüssel zu einer hohen – das heißt nahezu unbegrenzten – Leistung von Node.js-Anwendungen besteht darin, mehrere Anwendungsserver zu betreiben und die Last auf alle zu verteilen.
Der Lastenausgleich für Node.js kann besonders anspruchsvoll sein, da Node.js ein hohes Maß an Interaktion zwischen dem im Webbrowser ausgeführten JavaScript-Code und dem auf dem Node.js-Anwendungsserver ausgeführten JavaScript-Code ermöglicht, wobei JSON-Objekte als Medium für den Datenaustausch dienen. Dies bedeutet, dass eine bestimmte Clientsitzung kontinuierlich auf einem bestimmten Anwendungsserver ausgeführt wird und die Sitzungspersistenz bei mehreren Anwendungsservern grundsätzlich nur schwer zu gewährleisten ist.
Einer der größten Vorteile des Internets und des Webs ist ihr hohes Maß an Zustandslosigkeit. Dazu gehört, dass Clientanfragen von jedem Server beantwortet werden können, der Zugriff auf die angeforderte Datei hat. Node.js hebt diese Zustandslosigkeit auf und funktioniert am besten in einer zustandsbehafteten Umgebung, in der Anfragen bestimmter Clients stets vom selben Server beantwortet werden.
Diese Anforderung lässt sich am besten mit NGINX Plus statt mit NGINX Open Source erfüllen. Die beiden NGINX-Versionen sind sich recht ähnlich, unterscheiden sich jedoch wesentlich in der Unterstützung verschiedener Lastverteilungsalgorithmen.
NGINX unterstützt zustandslose Lastverteilungsverfahren:
- Round Robin – Eine neue Anfrage wird an den nächsten Server in einer Liste weitergeleitet.
- Wenigste Verbindungen – Eine neue Anfrage wird an den Server mit den wenigsten aktiven Verbindungen weitergeleitet.
- IP-Hash – Eine neue Anfrage wird an den Server weitergeleitet, der dem Hashwert der IP-Adresse des Clients zugewiesen ist.
Nur eine dieser Methoden, IP Hash, leitet die Anfragen eines bestimmten Clients zuverlässig an denselben Server weiter, was für Node.js-Anwendungen von Vorteil ist. Allerdings kann IP Hash leicht dazu führen, dass ein Server unverhältnismäßig viele Anfragen erhält, während andere Server weniger ausgelastet sind, wie in diesem Blogbeitrag über Lastverteilungstechniken beschrieben. Diese Methode ermöglicht Zustandsbehaftung, nimmt dafür jedoch eine potenziell suboptimale Verteilung der Anfragen auf die Serverressourcen in Kauf.
Im Gegensatz zu NGINX unterstützt NGINX Plus Sitzungspersistenz. Bei aktivierter Sitzungspersistenz werden alle Anfragen eines bestimmten Clients zuverlässig an denselben Server weitergeleitet. Dadurch kommen sowohl die Vorteile von Node.js mit seiner zustandsbehafteten Kommunikation zwischen Client und Server als auch die erweiterten Lastverteilungsfunktionen von NGINX Plus optimal zur Geltung.
Sie können also NGINX oder NGINX Plus verwenden, um die Lastverteilung auf mehrere Node.js-Server zu unterstützen. Allerdings können Sie nur mit NGINX Plus sowohl eine maximale Lastverteilungsleistung als auch eine für Node.js geeignete Zustandsbehaftung erreichen. Die in NGINX Plus integrierten Anwendungszustandsprüfungen und Überwachungsfunktionen sind hierbei ebenfalls hilfreich.
NGINX Plus unterstützt außerdem das Leeren von Sitzungen, wodurch ein Anwendungsserver laufende Sitzungen ordnungsgemäß abschließen kann, nachdem er angefordert hat, außer Betrieb genommen zu werden.
Tipp 4 – WebSocket-Verbindungen per Proxy weiterleiten
HTTP ist in allen Versionen für die „Pull“-Kommunikation ausgelegt, bei der der Client Dateien vom Server anfordert. WebSocket ermöglicht die „Push“- und „Push/Pull“-Kommunikation, bei der der Server proaktiv Dateien senden kann, die der Client nicht angefordert hat.
Das WebSocket-Protokoll erleichtert eine robustere Interaktion zwischen Client und Server und reduziert gleichzeitig die übertragene Datenmenge sowie die Latenz. Bei Bedarf lässt sich eine Vollduplexverbindung herstellen, bei der sowohl der Client als auch der Server nach Bedarf Anfragen initiieren und empfangen können.
Das WebSocket-Protokoll verfügt über eine robuste JavaScript-Schnittstelle und eignet sich daher ideal für Node.js als Anwendungsserver – und bei Webanwendungen mit moderatem Transaktionsvolumen auch als Webserver. Steigt das Transaktionsvolumen, ist es sinnvoll, NGINX zwischen den Clients und dem Node.js-Webserver einzusetzen und NGINX oder NGINX Plus zu verwenden, um statische Dateien zwischenzuspeichern und einen Lastenausgleich zwischen mehreren Anwendungsservern durchzuführen.
Node.js wird häufig in Verbindung mit Socket.IO verwendet – einer WebSocket-API, die für den Einsatz mit Node.js-Anwendungen sehr beliebt geworden ist. Dadurch können Port 80 (für HTTP) oder Port 443 (für HTTPS) stark ausgelastet werden. Die Lösung besteht darin, Anfragen über einen Proxy an den Socket.IO-Server weiterzuleiten. Sie können NGINX als Proxyserver verwenden, wie oben beschrieben, und zugleich zusätzliche Funktionen wie das Caching statischer Dateien, Lastverteilung und vieles mehr nutzen.

Im Folgenden finden Sie den Code für die Datei server.js einer Node-Anwendung, die Port 5000 überwacht. Sie fungiert als Proxyserver (nicht als Webserver) und leitet Anfragen an den richtigen Port weiter:
var io = require('socket.io').listen(5000);
io.sockets.on('connection', function (socket) {
socket.on('set nickname', function (name) {
socket.set('nickname', name, function () {
socket.emit('ready');
});
});
socket.on('msg', function () {
socket.get('nickname', function (err, name) {
console.log('Chat message by ', name);
});
});
});Fügen Sie in Ihrer Datei „index.html“ den folgenden Code hinzu, um eine Verbindung zu Ihrer Serveranwendung herzustellen und einen WebSocket zwischen der Anwendung und dem Browser des Benutzers zu erstellen:
<script src="/socket.io/socket.io.js"></script><script>// <![CDATA[
var socket = io(); // your initialization code here.
// ]]>
</script>Eine vollständige Anleitung einschließlich der NGINX-Konfiguration finden Sie in unserem Blogbeitrag über die Verwendung von NGINX und NGINX Plus mit Node.js und Socket.IO. Ausführlichere Informationen zu möglichen Architektur- und Infrastrukturfragen bei Webanwendungen dieser Art finden Sie in unserem Blogbeitrag über Echtzeit-Webanwendungen und WebSocket.
Tipp 5 – SSL/TLS und HTTP/2 implementieren
Immer mehr Websites verwenden SSL/TLS, um sämtliche Benutzerinteraktionen auf der Website abzusichern. Ob und wann Sie diesen Schritt gehen, liegt bei Ihnen. Wenn Sie sich jedoch dafür entscheiden, unterstützt NGINX die Umstellung auf zweierlei Weise:
- Nachdem Sie NGINX als Reverse-Proxy eingerichtet haben, können Sie die SSL/TLS-Verbindung zum Client in NGINX terminieren. Der Node.js-Server tauscht unverschlüsselte Anfragen und Inhalte mit dem NGINX-Reverse-Proxy-Server aus.
- Erste Anzeichen deuten darauf hin, dass die Verwendung von HTTP/2, der neuen Version des HTTP-Protokolls, die ansonsten durch den Einsatz von SSL/TLS verursachten Leistungseinbußen weitgehend oder vollständig ausgleichen kann. NGINX unterstützt HTTP/2, und Sie können HTTP/2 zusammen mit SSL/TLS terminieren, sodass auch hier keine Änderungen an den Node.js-Anwendungsservern erforderlich sind.
Zu den erforderlichen Implementierungsschritten gehören die Aktualisierung der URL in der Node.js-Konfigurationsdatei, die Einrichtung und Optimierung sicherer Verbindungen in Ihrer NGINX-Konfiguration sowie bei Bedarf die Verwendung von SPDY oder HTTP/2. Wenn Sie HTTP/2-Unterstützung hinzufügen, kommunizieren Browser-Versionen, die HTTP/2 unterstützen, über das neue Protokoll mit Ihrer Anwendung. Ältere Browser-Versionen verwenden weiterhin HTTP/1.x.

Der folgende Konfigurationscode ist für einen Ghost-Blog bestimmt, der SPDY verwendet, wie hier beschrieben. Er umfasst erweiterte Funktionen wie OCSP-Stapling. Hinweise zur Verwendung von NGINX für die SSL-Terminierung, einschließlich der Option für OCSP-Stapling, finden Sie hier. Einen allgemeinen Überblick über dieselben Themen finden Sie hier.
Sie müssen nur geringfügige Änderungen vornehmen, um Ihre Node.js-Anwendung zu konfigurieren und von SPDY auf HTTP/2 umzustellen – entweder jetzt oder wenn die Unterstützung für SPDY Anfang 2016 eingestellt wird.
server { server_name domain.com;
listen 443 ssl spdy;
spdy_headers_comp 6;
spdy_keepalive_timeout 300;
keepalive_timeout 300;
ssl_certificate_key /etc/nginx/ssl/domain.key;
ssl_certificate /etc/nginx/ssl/domain.crt;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 24h;
ssl_buffer_size 1400;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/trust.crt;
resolver 8.8.8.8 8.8.4.4 valid=300s;
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains';
add_header X-Cache $upstream_cache_status;
location / {
proxy_cache STATIC;
proxy_cache_valid 200 30m;
proxy_cache_valid 404 1m;
proxy_pass http://ghost_upstream;
proxy_ignore_headers X-Accel-Expires Expires Cache-Control;
proxy_ignore_headers Set-Cookie;
proxy_hide_header Set-Cookie;
proxy_hide_header X-powered-by;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
expires 10m;
}
location /content/images {
alias /path/to/ghost/content/images;
access_log off;
expires max;
}
location /assets {
alias /path/to/ghost/themes/uno-master/assets;
access_log off;
expires max;
}
location /public {
alias /path/to/ghost/built/public;
access_log off;
expires max;
}
location /ghost/scripts {
alias /path/to/ghost/core/built/scripts;
access_log off;
expires max;
}
location ~ ^/(?:ghost|signout) {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://ghost_upstream;
add_header Cache-Control "no-cache, private, no-store,
must-revalidate, max-stale=0, post-check=0, pre-check=0";
proxy_set_header X-Forwarded-Proto https;
}
}
Fazit
Dieser Blogbeitrag beschreibt einige der wichtigsten Leistungsoptimierungen, die Sie an Ihren Node.js-Anwendungen vornehmen können. Im Mittelpunkt steht die Ergänzung Ihrer Anwendungsumgebung aus Node.js und weiteren Komponenten um NGINX – als Reverse-Proxy-Server, zum Zwischenspeichern statischer Dateien, zur Lastverteilung, zur Weiterleitung von WebSocket-Verbindungen sowie zur Terminierung der Protokolle SSL/TLS und HTTP/2.
Die Kombination aus NGINX und Node.js ist weithin anerkannt als Möglichkeit, neue, für Microservices geeignete Anwendungen zu erstellen oder bestehende SOA-basierte Anwendungen, die Java oder Microsoft .NET verwenden, flexibler und leistungsfähiger zu machen. Dieser Beitrag hilft Ihnen, Ihre Node.js-Anwendungen zu optimieren und, wenn Sie möchten, die Zusammenarbeit zwischen Node.js und NGINX in die Praxis umzusetzen.
Über den Autor

Ähnliche Blogbeiträge
Die Zukunft von NGINX: Zurück zu unseren Open-Source-Wurzeln
Beim NGINX Sprint 2022 besinnen wir uns auf unsere Open-Source-Wurzeln. Erfahren Sie mehr über die Initiativen, die wir im kommenden Jahr verfolgen, und teilen Sie uns mit, was Sie sich wünschen.

Ein Leitfaden zur Auswahl eines Ingress-Controllers, Teil 1: Ermitteln Sie Ihre Anforderungen
Ein Ingress-Controller kann eines der leistungsstärksten Tools in Ihrem Kubernetes-Stack sein. Erfahren Sie, wie Sie Ihre Ingress-Anforderungen ermitteln, um die beste Option auszuwählen.
Bereitstellung des NGINX Ingress Controllers auf Amazon EKS: So haben wir getestet
Wir haben kürzlich den Lösungsleitfaden zum NGINX Ingress Controller um Empfehlungen zur Dimensionierung für Amazon Elastic Kubernetes Service (EKS) ergänzt. In diesem Blogbeitrag erläutern wir, wie wir diese Empfehlungen erarbeitet haben, und stellen Ihnen alle Informationen zur Verfügung, die Sie benötigen, um selbst ähnliche Tests durchzuführen.

Protokollierung des Datenverkehrs zwischen NGINX und Upstream-Servern bei CDN77
Bei der Fehlersuche bei Datenverkehrsproblemen zwischen NGINX und Upstream-Servern konnte CDN77 die benötigten Daten nur aus dem Fehlerprotokoll mit aktivierter Debug-Ausgabe beziehen, was die Leistung beeinträchtigt und riesige Dateien erzeugt. Daher entwickelte das Team ein neues benutzerdefiniertes Modul, das ausschließlich die benötigten Daten protokolliert.
Ankündigung von NGINX Plus R16
NGINX Plus R16 ist eine einheitliche, elastische Ingress- und Egress-Schicht für Anwendungen, die die Funktionen eines Load Balancers, API-Gateways und einer WAF vereint und neue Features wie clusterfähige Ratenbegrenzung, Schlüssel-Wert-Speicher, „Random with Two Choices“, verbessertes UDP-Load-Balancing und vieles mehr bietet.
5 Gründe für den Umstieg auf softwarebasiertes Load Balancing
Entdecken Sie fünf Gründe für den Wechsel zu einem softwarebasierten Load Balancer wie NGINX Plus, darunter Kosteneinsparungen, die Einführung von DevOps und eine einheitliche Lösung für alle Umgebungen.