Heim  >  Artikel  >  Web-Frontend  >  Eine eingehende Analyse von Multithreading und Multi-Processing in Node.js

Eine eingehende Analyse von Multithreading und Multi-Processing in Node.js

青灯夜游
青灯夜游nach vorne
2020-08-31 09:55:192571Durchsuche

Eine eingehende Analyse von Multithreading und Multi-Processing in Node.js

Node.js ist eine kostenlose plattformübergreifende JavaScript-Laufzeitumgebung, die zwar von Natur aus Single-Threaded ist, aber mehrere Threads im Hintergrund verwenden kann, um asynchronen Code auszuführen.

Aufgrund der nicht blockierenden Natur von Node.js führen verschiedene Threads unterschiedliche Rückrufe aus, die zunächst an die Ereignisschleife delegiert werden. All dies übernimmt die Node.js-Laufzeitumgebung. [Empfehlung für ein Video-Tutorial: Node-JS-Tutorial]

Warum NodeJS verwenden?

JavaScript wurde ursprünglich als Single-Threaded-Programmiersprache entwickelt, die nur in einem Webbrowser lief. Das bedeutet, dass innerhalb eines Prozesses jeweils nur ein Befehlssatz ausgeführt werden kann.

Erst zum nächsten Codeblock wechseln, nachdem die Ausführung des aktuellen Codeblocks abgeschlossen ist. Der Single-Thread-Charakter von JavaScript erleichtert jedoch die Implementierung.

Anfangs wurde JavaScript nur verwendet, um Websites in geringem Maße interaktiv zu gestalten. Es ist also kein Multithreading erforderlich. Aber die Zeiten haben sich geändert, die Benutzer sind anspruchsvoller geworden und JavaScript ist zur „beliebtesten Programmiersprache im Web“ geworden.

Multithreading wird heutzutage immer häufiger. Da es sich bei JavaScript um eine Single-Thread-Sprache handelt, kann darin kein Multi-Threading implementiert werden. Glücklicherweise gibt es für diesen Fall eine tolle Lösung: Node.js.

Node.js-FrameworksAn ihnen mangelt es nicht, dank der allgemeinen Beliebtheit von JavaScript-Laufzeitumgebungen (insbesondere JavaScript). Bevor wir mit diesem Artikel fortfahren, lassen Sie uns einige wichtige Punkte zu Node.js verstehen:

  1. Sie können die Sendefunktion verwenden, um Nachrichten von untergeordneten Prozessen an andere untergeordnete Prozesse und den Hauptprozess weiterzuleiten.
  2. Unterstützt das Forken mehrerer Prozesse.
  3. Hauptprozess und untergeordnete Prozesse Der Status wird nicht zwischen ihnen geteilt

Warum müssen wir den Prozess forken?

In zwei Fällen müssen wir einen Prozess forken:

  1. Um die Geschwindigkeit zu erhöhen, indem Aufgaben an andere Prozesse delegiert werden
  2. Um Speicher freizugeben und einen einzelnen Prozess zu entladen

Kann Daten an einen untergeordneten Prozess senden oder zurücksenden.

Der Node.js-Weg

Node.js verwendet zwei Arten von Threads:

  1. Der Hauptthread wird über eine Ereignisschleife verarbeitet.
  2. Es gibt viele sekundäre Threads im Worker-Pool.

Die Ereignisschleife ist dafür verantwortlich zum Abrufen von Rückrufen oder Funktionen und registrieren Sie es für die zukünftige Ausführung. Es läuft im selben Thread wie der richtige JavaScript-Code. Sobald eine JavaScript-Operation den Thread blockiert, wird auch die Ereignisschleife blockiert.

Ein Arbeitspool ist ein Ausführungsmodell, das für das Erzeugen und Verarbeiten verschiedener Threads verantwortlich ist. Es führt die Aufgabe synchron aus, gibt dann das Ergebnis an die Ereignisschleife zurück und schließlich stellt die Ereignisschleife das Ergebnis dem Rückruf zur Verfügung.

Zusammenfassend lässt sich sagen, dass der Worker-Pool für asynchrone I/O-Vorgänge verantwortlich ist, also für Interaktionen mit der Systemfestplatte und dem Netzwerk. Module wie fs und crypto sind die Hauptmodule, die Worker-Pools verwenden.

Da der Worker-Pool in der libuv-Bibliothek implementiert ist, kommt es bei Node.js zu einer leichten Verzögerung bei der internen Kommunikation zwischen JS und C++. Aber es ist fast nicht wahrnehmbar.

Alles war in Ordnung, bis wir auf die Anforderung stießen, komplexe Vorgänge synchron auszuführen. Jede Funktion, deren Ausführung viel Zeit in Anspruch nimmt, führt zur Blockierung des Hauptthreads.

Wenn ein Programm über mehrere CPU-intensive Funktionen verfügt, führt dies zu einem erheblichen Rückgang des Serverdurchsatzes. Im schlimmsten Fall reagiert der Server nicht mehr und kann keine Aufgaben an den Worker-Pool delegieren.

Bereiche wie KI, Big Data und maschinelles Lernen können nicht von Node.js profitieren, da diese Vorgänge den Hauptthread blockieren und den Server nicht mehr reagieren lassen. Dies ändert sich jedoch mit der Einführung von Node.js v10.5.0, das Unterstützung für Multithreading hinzufügt.

Herausforderungen durch Parallelität und CPU-gebundene Aufgaben

Der Aufbau von Parallelität in JavaScript kann schwierig sein. Wenn mehreren Threads der Zugriff auf denselben Speicher gestattet wird, kann dies zu Race-Bedingungen führen, die nicht nur die Reproduktion des Fehlers erschweren, sondern auch die Behebung erschweren.

Node.js wurde ursprünglich als serverseitige Plattform basierend auf asynchronem I/O implementiert. Dadurch wird vieles einfacher, da Threads einfach wegfallen. Ja, Node.js-Programme sind Single-Threaded, aber nicht auf die typische Art und Weise.

Wir können Node.js parallel ausführen, es ist jedoch nicht erforderlich, Threads zu erstellen. Das Betriebssystem und die virtuelle Maschine arbeiten zusammen, um E/A parallel zu nutzen. Wenn dann Daten an den JavaScript-Code zurückgesendet werden müssen, wird der JS-Code in einem einzelnen Thread ausgeführt.

Alles läuft parallel in Node.js außer dem JS-Code. Im Gegensatz zu asynchronen Blöcken werden synchrone Blöcke in JS immer einmal ausgeführt. Das Warten auf das Eintreten von E/A-Ereignissen in JS nimmt viel mehr Zeit in Anspruch als das Ausführen von Code.

Node.js-Programme rufen nur die erforderlichen Funktionen oder Rückrufe auf, ohne die Ausführung anderen Codes zu blockieren. Ursprünglich waren weder JavaScript noch Node.js für die Bewältigung CPU-intensiver oder CPU-gebundener Aufgaben gedacht.

Wenn der Code minimal ist, erfolgt die Ausführung agil. Aber je größer der Rechenaufwand, desto langsamer ist die Ausführungsgeschwindigkeit.

Wenn Sie dennoch versuchen, CPU-intensive Aufgaben in JS und Node abzuschließen, friert die Benutzeroberfläche im Browser ein und alle E/A-Ereignisse werden in die Warteschlange gestellt. Dennoch haben wir einen langen Weg zurückgelegt. Jetzt gibt es das Modul worker_threads.

worker_threads-Modul macht Multithreading einfach

Node.js v10.5.0 wurde im Juni 2018 veröffentlicht und führt das worker_threads-Modul ein. Es trägt dazu bei, Parallelität in gängigen JavaScript-Laufzeitumgebungen zu erreichen. Dieses Modul ermöglicht die Erstellung voll funktionsfähiger Multithread-Node.js-Anwendungen.

Technisch gesehen ist ein Arbeitsthread ein Code, der in einem separaten Thread erzeugt wird. Um mit der Verwendung von Worker-Threads zu beginnen, müssen Sie zuerst das Modul worker_threads importieren. Anschließend müssen Sie eine Instanz der Worker-Klasse erstellen, um einen Worker-Thread zu erstellen.

Beim Erstellen einer Instanz der Worker-Klasse gibt es zwei Parameter:

  1. Der erste Parameter stellt einen Dateipfad mit der Erweiterung .js oder .mjs bereit, der den Code für den Worker-Thread enthält.
  2. Der zweite Parameter stellt einen An bereit Objekt, das die workerData-Eigenschaft enthält, die die Daten enthält, auf die der Arbeitsthread zugreift, wenn er mit der Ausführung beginnt.

Der Arbeitsthread kann mehrere Nachrichtenereignisse versenden. Daher haben Rückrufmethoden Vorrang vor Rückgabeversprechen.

Die Kommunikation zwischen Worker-Threads ist ereignisbasiert, d. h. der Listener wird so eingestellt, dass er sofort aufgerufen wird, nachdem der Worker-Thread das Ereignis sendet. Die 4 häufigsten Ereignisse sind:

worker.on('error', (error) => {});
  1. Wird ausgegeben, wenn im Worker-Thread eine nicht abgefangene Ausnahme vorliegt. Als nächstes wird der Arbeitsthread beendet und der Fehler steht als erstes Argument im Rückruf zur Verfügung.
worker.on('exit', (exitCode) => {})
  1. Wird ausgegeben, wenn der sekundäre Thread beendet wird. Wenn process.exit(),则会将 exitCode 提供给回调。如果 worker.terminate() in einem Arbeitsthread aufgerufen wird, um den Arbeitsthread zu beenden, ist der Code 1.
worker.on('message', (data) => {});
  1. Wird ausgegeben, wenn der Arbeitsthread Daten an den übergeordneten Thread sendet.
worker.on('online', () => {});
  1. Wird ausgegeben, wenn der Arbeitsthread das Parsen von JS-Code beendet und mit der Ausführung beginnt. Obwohl die Online-Veranstaltung nicht häufig verwendet wird, kann sie in bestimmten Situationen mehr Informationen liefern.

Möglichkeiten zur Verwendung von Arbeitsthreads

Es gibt zwei Möglichkeiten, Arbeitsthreads zu verwenden:

  • Methode 1 – beinhaltet das Erzeugen eines Arbeitsthreads, das Ausführen seines Codes und das Senden der Ergebnisse an den übergeordneten Thread. Bei dieser Methode muss jedes Mal für eine neue Aufgabe ein neuer Arbeitsthread von Grund auf erstellt werden.
  • Methode 2 – Beinhaltet das Erstellen eines Arbeitsthreads und das Einrichten von Listenern für Nachrichtenereignisse. Jedes Mal, wenn die Nachricht ausgelöst wird, führt der Arbeitsthread den Code aus und sendet die Ergebnisse zurück an den übergeordneten Thread. Der Arbeitsthread wird für die zukünftige Verwendung am Leben gehalten.

Methode 2 wird auch als Worker-Pool bezeichnet. Dies liegt daran, dass die Methode das Erstellen eines Pools von Arbeitern, deren Warten und das Versenden von Nachrichtenereignissen beinhaltet, um bei Bedarf Aufgaben auszuführen.

Da das Erstellen eines Arbeitsthreads von Grund auf das Erstellen einer virtuellen Maschine sowie das Parsen und Ausführen von Code erfordert, empfiehlt die offizielle Node.js-Dokumentation Methode 2. Darüber hinaus ist Methode 2 praktischer und effektiver als Methode 1.

Wichtige Eigenschaften im worker_threads-Modul verfügbar

  • isMainThread – Diese Eigenschaft ist wahr, wenn sie nicht in einem Worker-Thread ausgeführt wird. Bei Bedarf können Sie eine einfache if-Anweisung am Anfang der Arbeitsdatei einfügen. Dadurch wird sichergestellt, dass es nur als Arbeitsthread ausgeführt wird.
  • parentPort – Eine Instanz von MessagePort, die zur Kommunikation mit dem übergeordneten Thread verwendet wird.
  • threadId – Eindeutige Kennung, die dem Arbeitsthread zugewiesen ist.
  • workerData – Daten, die im Konstruktor des Worker-Threads enthalten sind.

Mehrere Prozesse in Node.js

Damit Node.js die Fähigkeiten eines Multi-Core-Systems nutzen kann, können einige Prozesse verwendet werden. Die beliebte JavaScript-Laufzeitumgebung verfügt über ein Modul namens Cluster, das Unterstützung für mehrere Prozesse bietet.

Verwenden Sie das Cluster-Modul, um mehrere untergeordnete Prozesse zu erzeugen, die einen gemeinsamen Port teilen können. Systeme, die NodeJS verwenden, können größere Arbeitslasten bewältigen, wenn untergeordnete Prozesse verwendet werden.

Node.js im Backend

Das Internet ist für Millionen von Unternehmen auf der ganzen Welt zur bevorzugten Plattform geworden. Damit ein Unternehmen sein maximales Potenzial ausschöpfen und sich dabei von anderen abheben kann, ist eine starke Online-Präsenz erforderlich.

Alles beginnt mit einer leistungsstarken und intuitiven Website. Um eine einwandfreie Website zu erstellen, ist es wichtig, die besten Front-End- und Back-End-Technologien auszuwählen. Obwohl Node.js von Natur aus Single-Threaded ist, ist es die erste Wahl für die Entwicklung von Backend-Webdiensten.

Trotz der Fülle an Backend-Multithreading-Optionen bevorzugen namhafte Unternehmen Node.js. Dies liegt daran, dass Node.js Workarounds für die Verwendung von Multithreading in JavaScript bietet, das bereits „die beliebteste Programmiersprache im Web“ ist.

Zusammenfassung

Das worker_threads-Modul bietet eine einfache Möglichkeit, Multithreading in Node.js-Programmen zu implementieren. Indem Sie umfangreiche Berechnungen an Arbeitsthreads delegieren, können Sie den Durchsatz Ihres Servers erheblich steigern.

Mit der Unterstützung von Multithreading wird Node.js weiterhin eine wachsende Zahl von Entwicklern, Ingenieuren und anderen Fachleuten aus rechenintensiven Bereichen wie KI, Big Data und maschinellem Lernen anziehen.

Englische Originaladresse: https://flatlogic.com/blog/multi-threading-and-multiple-process-in-node-js/

Um die Lesbarkeit zu gewährleisten, verwendet dieser Artikel eine freie Übersetzung anstelle einer wörtlichen Übersetzung .

Weitere Kenntnisse zum Thema Programmierung finden Sie unter: Programmierunterricht! !

Das obige ist der detaillierte Inhalt vonEine eingehende Analyse von Multithreading und Multi-Processing in Node.js. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen