Node.js auf Mehrkernmaschinen

Lesezeit: 10 Minuten

Nodejs auf Mehrkernmaschinen
Zaharpopov

Node.js sieht interessant aus, ABER Ich muss etwas übersehen – ist Node.js nicht darauf abgestimmt, nur auf einem einzelnen Prozess und Thread ausgeführt zu werden?

Wie skaliert es dann für Multi-Core-CPUs und Multi-CPU-Server? Immerhin ist es toll, Single-Thread-Server möglichst schnell zu machen, aber für hohe Lasten würde ich mehrere CPUs einsetzen wollen. Und das Gleiche gilt für die Beschleunigung von Anwendungen – heute scheint der Weg darin zu bestehen, mehrere CPUs zu verwenden und die Aufgaben zu parallelisieren.

Wie passt Node.js in dieses Bild? Ist seine Idee, irgendwie mehrere Instanzen zu verteilen, oder was?

Nodejs auf Mehrkernmaschinen
David Dopson

[This post is up-to-date as of 2012-09-02 (newer than above).]

Node.js skaliert absolut auf Mehrkernmaschinen.

Ja, Node.js ist ein Thread pro Prozess. Dies ist eine sehr bewusste Entwurfsentscheidung und beseitigt die Notwendigkeit, sich mit Sperrsemantik zu befassen. Wenn Sie dem nicht zustimmen, wissen Sie wahrscheinlich noch nicht, wie wahnsinnig schwer es ist, Multithread-Code zu debuggen. Für eine tiefere Erklärung des Node.js-Prozessmodells und warum es so funktioniert (und warum es NIEMALS mehrere Threads unterstützen wird), lesen Sie meinen anderen Beitrag.

Wie nutze ich also meine 16-Core-Box?

Zwei Wege:

  • Für große Rechenaufgaben wie die Bildcodierung kann Node.js untergeordnete Prozesse starten oder Nachrichten an zusätzliche Worker-Prozesse senden. In diesem Design hätten Sie einen Thread, der den Ereignisfluss verwaltet, und N Prozesse, die schwere Rechenaufgaben erledigen und die anderen 15 CPUs belasten.
  • Um den Durchsatz auf einem Webdienst zu skalieren, sollten Sie mehrere Node.js-Server auf einer Box ausführen, einen pro Kern, und den Anforderungsverkehr zwischen ihnen aufteilen. Dies bietet eine hervorragende CPU-Affinität und skaliert den Durchsatz nahezu linear mit der Anzahl der Kerne.

Skalieren des Durchsatzes auf einem Webdienst

Seit v6.0.X ist Node.js enthalten das Clustermodul sofort einsatzbereit, was es einfach macht, mehrere Node-Worker einzurichten, die auf einem einzelnen Port lauschen können. Beachten Sie, dass dies NICHT dasselbe ist wie das ältere Learnboost-Modul “Cluster”, das über verfügbar ist npm.

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  http.Server(function(req, res) { ... }).listen(8000);
}

Worker konkurrieren darum, neue Verbindungen zu akzeptieren, und der am wenigsten belastete Prozess gewinnt am ehesten. Es funktioniert ziemlich gut und kann den Durchsatz auf einer Multi-Core-Box ziemlich gut skalieren.

Wenn Sie genug Last haben, um sich um mehrere Kerne zu kümmern, sollten Sie auch noch ein paar Dinge tun:

  1. Führen Sie Ihren Node.js-Dienst hinter einem Webproxy wie z Nginx oder Apache – etwas, das Verbindungsdrosselung bewirken kann (es sei denn, Sie möchten, dass Überlastbedingungen die Box vollständig zum Erliegen bringen), URLs umschreiben, statische Inhalte bereitstellen und andere Unterdienste weiterleiten.

  2. Recyceln Sie regelmäßig Ihre Worker-Prozesse. Bei einem lang andauernden Prozess summiert sich schließlich sogar ein kleines Speicherleck.

  3. Log-Sammlung/-Überwachung einrichten


PS: Es gibt eine Diskussion zwischen Aaron und Christopher in den Kommentaren eines anderen Posts (zum jetzigen Zeitpunkt ist es der oberste Post). Ein paar Anmerkungen dazu:

  • Ein Shared-Socket-Modell ist sehr praktisch, um es mehreren Prozessen zu ermöglichen, auf einem einzigen Port zu lauschen und um die Annahme neuer Verbindungen zu konkurrieren. Konzeptionell könnte man sich vorstellen, dass Apache dies vorab gegabelt tut, mit der erheblichen Einschränkung, dass jeder Prozess nur eine einzige Verbindung akzeptiert und dann stirbt. Der Effizienzverlust für Apache liegt im Overhead beim Forken neuer Prozesse und hat nichts mit den Socket-Operationen zu tun.
  • Für Node.js ist es eine äußerst vernünftige Lösung, N Worker auf einem einzigen Socket konkurrieren zu lassen. Die Alternative besteht darin, ein On-Box-Front-End wie Nginx einzurichten und diesen Proxy-Verkehr zu den einzelnen Workern zu leiten, wobei zwischen den Workern gewechselt wird, um neue Verbindungen zuzuweisen. Die beiden Lösungen haben sehr ähnliche Leistungsmerkmale. Und da Sie, wie ich oben erwähnt habe, wahrscheinlich sowieso Nginx (oder eine Alternative) vor Ihrem Knotendienst haben möchten, haben Sie hier wirklich die Wahl zwischen:

Freigegebene Ports: nginx (port 80) --> Node_workers x N (sharing port 3000 w/ Cluster)

vs

Einzelne Häfen: nginx (port 80) --> {Node_worker (port 3000), Node_worker (port 3001), Node_worker (port 3002), Node_worker (port 3003) ...}

Es gibt wohl einige Vorteile für die Einrichtung einzelner Ports (möglicherweise weniger Kopplung zwischen Prozessen, ausgefeiltere Lastausgleichsentscheidungen usw.), aber die Einrichtung ist definitiv arbeitsaufwändiger und das integrierte Clustermodul ist niedrig -Komplexitätsalternative, die für die meisten Menschen funktioniert.

  • Können Sie Ratschläge geben, wie Sie verschiedene nodejs-basierte Dienste auf einer Box ausführen können? Angenommen, ich habe 1 Server und möchte myservice1.js auf CpuCore1 und myservice2.js auf CpuCore2 ausführen. Kann ich dafür Cluster verwenden? oder ist es nur nützlich, um geklonte Dienste zu erstellen?

    – UpTheCreek

    20. September 2012 um 14:36 ​​Uhr

  • Dazu solltest du eine Frage posten! (und ich werde diesen Kommentar als Ihre erste Antwort kopieren). Was Sie tun möchten, ist eigentlich wirklich sehr einfach. Sie würden “Cluster” nicht wirklich brauchen, Sie würden nur zwei verschiedene Knotendienste ausführen. Zwei Skripte, zwei Prozesse, zwei Ports. Beispielsweise könnten Sie ServiceA auf 3000 und ServiceB auf 3001 abhören lassen. Jeder dieser Dienste könnte “Cluster” verwenden, um 1+ Worker zu haben und sie regelmäßig zu recyceln usw. Dann könnten Sie Nginx so konfigurieren, dass es auf Port 80 lauscht und weiterleitet den richtigen Dienst basierend auf dem eingehenden “Host”-Header und/oder dem URL-Pfad.

    – David Dopson

    20. September 2012 um 16:56 Uhr

  • Danke. Ich habe bereits eine verwandte Frage gestellt – Sie haben ziemlich genau beschrieben, was ich mir vorgestellt habe, aber ich bin mir nicht sicher, wie ich auf CPU-Kerne abzielen soll (wenn ich so etwas wie forever verwende).

    – UpTheCreek

    20. September 2012 um 18:01 Uhr

  • Tolle Antwort ddopson. Was ist der beste Weg, um zwei Knotenprozesse auf derselben Maschine miteinander kommunizieren zu lassen? Gibt es ein schnelleres Protokoll als TCP, wenn sie sich auf derselben Maschine befinden?

    – Aufzieh Spielzeug

    16. Januar 2013 um 7:31 Uhr

  • @Serob_b – na ja. Das Ausführen einer Node.js-App auf mehreren Computern ist weit verbreitet. Dazu ist keine Bibliothek erforderlich. Sie führen Ihren Code einfach auf mehreren Computern aus und verteilen die Last zwischen ihnen. Ihre Software so zu gestalten, dass sie skalierbar ist (dh sie speichert den Status in einer Art externem Datendienst, anstatt den Status im Speicher zu halten) – das ist Ihre Aufgabe.

    – David Dopson

    19. Januar 2017 um 18:18 Uhr

Eine Methode wäre, mehrere Instanzen von node.js auf dem Server auszuführen und ihnen dann einen Load Balancer (vorzugsweise einen nicht blockierenden wie nginx) vorzusetzen.

  • node.js ist ungefähr so ​​​​schnell wie nginx, Sie könnten einen node.js-Load-Balancer vor Ihren node.js-Servern platzieren, wenn Sie dies auch möchten 🙂

    – Mikel

    13. März 2010 um 18:47 Uhr

  • Ryan hat ausdrücklich gesagt, dies nicht zu tun, bis der Knoten stabiler ist. Der beste Weg ist, nginx vor dem Knoten auszuführen.

    – Resoverschmutzung

    29. Juli 2010 um 9:52 Uhr

  • Was nginx vor dem Knoten angeht, löst es bestimmte Probleme nicht, z. B. wenn Sie eine In-Memory-Warteschlange haben. 2 Knoteninstanzen können nicht auf die Warteschlange der anderen zugreifen.

    – Resoverschmutzung

    29. Juli 2010 um 9:54 Uhr

  • Außerdem unterstützt nginx HTTP 1.1 nicht vollständig, sodass Dinge wie WebSockets nicht per Proxy ausgeführt werden können.

    – Aschechristoph

    13. April 2011 um 14:28 Uhr

  • @mikeal, Resoverschmutzung – Ich bin stark auf der Seite von Nginx. Ich habe Node.js mehrmals hart abgestürzt (kein Stacktrace, stirbt einfach). Ich habe Nginx noch nie zum Absturz gebracht. Nginx ist standardmäßig mit allen möglichen vernünftigen Drosseln konfiguriert. Node.js akzeptiert standardmäßig weiterhin neue Verbindungen, anstatt vorhandene zu bedienen, bis die Box ausfällt … ja, die gesamte Box; Ich habe den Kernel auf einer CentOS5-Box durch Stresstests von Node zum Absturz gebracht (das sollte jetzt wirklich nicht passieren). Ich bin ein bisschen herumgekommen und sehe eine glänzende Zukunft für Node, möglicherweise mit dedizierten LB-Rollen. Nur noch nicht.

    – David Dopson

    16. Januar 2013 um 18:16 Uhr

Nodejs auf Mehrkernmaschinen
broofa

Ryan Dahl beantwortet diese Frage in der Tech-Talk, den er bei Google hielt letzten Sommer. Um es anders auszudrücken: “Führen Sie einfach mehrere Knotenprozesse aus und verwenden Sie etwas Vernünftiges, um ihnen die Kommunikation zu ermöglichen, z. B. sendmsg()-artiges IPC oder traditionelles RPC”.

Wenn Sie sich gleich die Hände schmutzig machen wollen, schauen Sie sich das an Funke2 Für immer Modul. Es macht das Spawnen mehrerer Knotenprozesse trivial einfach. Es übernimmt die Einrichtung der Portfreigabe, sodass sie jeweils Verbindungen zum selben Port akzeptieren können, und auch das automatische Respawnen, wenn Sie sicherstellen möchten, dass ein Prozess neu gestartet wird, wenn er stirbt.

UPDATE – 11.10.11: Konsens in der Node-Community scheint das zu sein Cluster ist jetzt das bevorzugte Modul für die Verwaltung mehrerer Knoteninstanzen pro Maschine. Für immer ist auch einen blick wert.

  • Forever und Cluster machen sehr unterschiedliche Dinge. Sie können sogar beide verwenden. Forever startet einen Prozess neu, wenn er stirbt. Cluster verwaltet mehrere Worker. Sie würden Forever verwenden, um Ihren Master-Prozess zu verwalten …

    – David Dopson

    7. Februar 2012 um 23:28 Uhr

  • Außerdem wird das Learnboost-Modul weitgehend durch die in Node v0.6.x gebackene Cluster-Version ersetzt (Warnung: Die API-Oberfläche unterscheidet sich).

    – David Dopson

    7. Februar 2012 um 23:28 Uhr

  • @broofa Wie ist der Standard-IPC im Vergleich zu Redis oder Memcache, wenn nur Zeichenfolgen/Daten/Arrays zwischen Prozessen gesendet werden? Welcher Weg wäre schneller?

    – Nick Newman

    4. September 2015 um 5:27 Uhr

  • @broofa, IPC hat im Vergleich zu echtem Shared Memory, zu dem Java und C in der Lage sind, enorme Overheads.

    – Schrittmacher

    28. Februar 2017 um 17:09 Uhr


  • @Pacerier Stimmt, aber Shared Memory löst nur das Problem der Skalierung im Kontext eines einzelnen Hosts, ohne die Makroprobleme zu lösen, die für die Skalierung über viele Hosts erforderlich sind. Dh wie man in der Cloud läuft.

    – broofa

    1. März 2017 um 17:01 Uhr

1647261923 642 Nodejs auf Mehrkernmaschinen
Sergej Schukow

Sie können verwenden Cluster Modul. Überprüfen Das.

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
    // Fork workers.
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    cluster.on('exit', function(worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' died');
    });
} else {
    // Workers can share any TCP connection
    // In this case its a HTTP server
    http.createServer(function(req, res) {
        res.writeHead(200);
        res.end("hello world\n");
    }).listen(8000);
}

1647261924 768 Nodejs auf Mehrkernmaschinen
Toumi

Node Js unterstützt Clustering, um die Vorteile Ihrer CPU voll auszuschöpfen. Wenn Sie es nicht mit Cluster ausführen, verschwenden Sie wahrscheinlich Ihre Hardwarekapazitäten.

Clustering in Node.js ermöglicht es Ihnen, separate Prozesse zu erstellen, die denselben Serverport teilen können. Wenn wir beispielsweise einen HTTP-Server auf Port 3000 ausführen, handelt es sich um einen Server, der auf einem einzelnen Thread auf einem einzelnen Prozessorkern ausgeführt wird.

Der unten gezeigte Code ermöglicht es Ihnen, Ihre Anwendung zu clustern. Dieser Code ist offizieller Code, der durch Node.js dargestellt wird.

var cluster = require('cluster');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
    // Fork workers.
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    Object.keys(cluster.workers).forEach(function(id) {
        console.log("I am running with ID : " + cluster.workers[id].process.pid);
    });

    cluster.on('exit', function(worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' died');
    });
} else {

    //Do further processing.
}

Lesen Sie diesen Artikel vollständig Lernprogramm

1647261924 539 Nodejs auf Mehrkernmaschinen
CyberFonic

Multi-Node nutzt alle Kerne, die Sie möglicherweise haben.
Schau mal rein http://github.com/kriszyp/multi-node.

Für einfachere Anforderungen können Sie mehrere Knotenkopien auf verschiedenen Portnummern starten und ihnen einen Load Balancer vorschalten.

Wie oben erwähnt, Cluster skaliert und verteilt Ihre App über alle Kerne hinweg.

Hinzufügen von etwas wie

cluster.on('exit', function () {
  cluster.fork();
});

Wird alle fehlerhaften Worker neu starten.

Heutzutage bevorzugen viele Leute auch PM2die das Clustering für Sie übernimmt und auch bereitstellt einige coole Überwachungsfunktionen.

Fügen Sie dann Nginx oder HAProxy vor mehreren Computern hinzu, auf denen Clustering ausgeführt wird, und Sie haben mehrere Failover-Ebenen und eine viel höhere Lastkapazität.

  • PM2 eignet sich hervorragend für den Produktionseinsatz. Die Überwachungstools haben mir geholfen, Speicherprobleme mit Apps zu lösen.

    – mbokil

    15. März 2016 um 19:20 Uhr

1001590cookie-checkNode.js auf Mehrkernmaschinen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy