Node.js 10.5 Release: Multithreading sofort einsatzbereit


Letzte Woche wurde Node.js Version 10.5.0 veröffentlicht, die eine Innovation enthält, deren Bedeutung kaum überschätzt werden kann - Multithreading-Unterstützung in Form des Worker_Threads- Moduls. Ich werde sofort eine Reservierung vornehmen. Die API befindet sich im experimentellen Stadium und kann sich daher ändern. Jetzt können Sie jedoch einen ersten Eindruck hinterlassen und sich ein Bild von den Prinzipien und Technologien machen, die in ihrer Grundlage festgelegt sind. Und wenn Sie einen Wunsch haben, nehmen Sie an der Fertigstellung der Benutzeroberfläche, dem Schreiben von Code oder der Behebung von Fehlern teil (Liste der Probleme ).


Erscheinungsgeschichte


Während des gesamten Lebens von Node.j bestand die einzige Möglichkeit, das Computing zu parallelisieren, darin, einen neuen Prozess zu starten, beispielsweise mithilfe des Cluster-Moduls. Aus vielen Gründen eignet sich dieser Ansatz nicht für Entwickler, insbesondere weil er dazu führt, dass der ausführbare Code von Node.j mit allen integrierten Modulen wiederholt in den Arbeitsspeicher des Computers geladen wird. Dies ist eine ineffiziente Methode, um Ressourcen zu verbrauchen.


Die Diskussion über die Implementierung von Multithreading in Node.js beruhte jedoch immer auf der Komplexität von V8 und einer Vielzahl von Unbekannten: wie man native Module verbindet, Speicher gemeinsam nutzt, zwischen Threads kommuniziert und vieles mehr. Und während die Entwickler nach einer Seite suchten, um sich dem Thema im Web zu nähern, wurde die Worker-API erfolgreich implementiert, was in der Anfangsphase zu einer Richtlinie wurde. Die Entwicklung begann mit Addaleax und wurde von der Community übernommen.


Die aktive Arbeit wurde in dem Jahr ausgeführt, in dem die Entwurfsanforderungen festgelegt wurden und die API ihre eigenen Node.js-spezifischen Funktionen erwarb. Das Modul selbst hieß worker_threads. Im Folgenden werde ich worker_threads kurz allgemein beschreiben. Für eine detaillierte Studie empfehle ich Ihnen, die offizielle Dokumentationsseite zu besuchen.


Beschreibung


Wie oben erwähnt, besteht das Ziel dieser Entwicklung darin, die Produktivität zu verbessern, indem die Last auf separate Threads innerhalb desselben Prozesses verteilt wird, anstatt mehrere Prozesse zu starten. Daher unterstützen Threads die Verbindung aller verfügbaren Module zum Hauptprozess (derzeit werden native Module nicht unterstützt).


Wie in der Worker-API wird die Interaktion zwischen dem Haupt- und dem untergeordneten Stream durch Übertragen übertragbarer Objekte über postMessage ausgeführt, wodurch die Probleme des gleichzeitigen Zugriffs vermieden werden, obwohl zusätzliche Speicherzugriffe zum Kopieren von Daten erforderlich sind. In diesem Fall behalten Objekte wie SharedArrayBuffer ihr Verhalten bei und verursachen keine Neuzuweisung.


MessageChannel und MessagePort wurden aus der WebAPI übernommen , mit der Sie isolierte Messaging-Kanäle erstellen und zwischen Threads übertragen können.


Um worker_threads in Aktion zu testen, müssen Sie beim Starten des Prozesses ein spezielles Flag angeben:


node --experimental-worker main.js 

Beispiel


Da sich die API möglicherweise noch ändert, werde ich sie nicht beschreiben, aber ich werde ein Beispiel für einen Nachrichtenaustausch zwischen dem übergeordneten und dem untergeordneten Thread geben, in dem der untergeordnete Thread seine threadId über MessagePort meldet und beendet.


Hauptstrom


Beispielcode für den Hauptthread:


 // main.js const {Worker} = require('worker_threads'); const worker = new Worker(__dirname + '/worker.js'); worker.on('online', () => { console.log('Worker ready'); }); worker.on('message', (msg) => { console.log('Worker message:', msg); }); worker.on('error', (err) => { console.error('Worker error:', err); }); worker.on('exit', (code) => { console.log('Worker exit code:', code); }); 

Untergeordneter Stream


Der untergeordnete Thread bleibt so lange bestehen, bis seine Ereignisschleife leer ist. Daher worker.js Thread unmittelbar nach der worker.js des Codes aus worker.js automatisch geschlossen. Für die Kommunikation mit dem übergeordneten Element wird parentPort verwendet:


 // worker.js const {threadId, parentPort} = require('worker_threads'); parentPort.postMessage(`Hello from thread #${threadId}.`); // Exit happens here 

Im untergeordneten Thread wird das Prozessobjekt überschrieben, und sein Verhalten unterscheidet sich geringfügig vom Prozessverhalten im übergeordneten Thread. Insbesondere gibt es keine Möglichkeit, auf SIGNINT-Signale zu reagieren, die Werte von process.env zu ändern, und das Aufrufen von process.exit stoppt nur den Worker, aber nicht den gesamten Prozess.


Fazit


Die Mitarbeiter werden die Erstellung von Anwendungen, die die Interaktion zwischen parallelen ausführbaren Codeabschnitten erfordern, erheblich vereinfachen und, was besonders wichtig ist, die Kommunikation und Flusskontrolle am offensichtlichsten machen. Außerdem können plattformspezifische Einschränkungen vermieden werden, die durch den Unterschied zwischen Windows und Unix verursacht werden. Ich bin sicher, dass die sich bietenden Möglichkeiten neue Entwickler anziehen werden, die sich noch nicht für Node.js entschieden haben. Überwachen Sie in der Zwischenzeit weiterhin die Änderungen und stellen Sie eine Verbindung zum API-Entwicklungsprozess im Repository her .


Referenzen


Source: https://habr.com/ru/post/de415165/


All Articles