Was ist Node.js? Die JavaScript-Laufzeit erklärt

Skalierbarkeit, Latenz und Durchsatz sind wichtige Leistungsindikatoren für Webserver. Es ist nicht einfach, die Latenz niedrig und den Durchsatz hoch zu halten, während die Größe vergrößert und verkleinert wird. Node.js ist eine JavaScript-Laufzeitumgebung, die eine geringe Latenz und einen hohen Durchsatz erzielt, indem Anforderungen nicht blockiert werden. Mit anderen Worten, Node.js verschwendet keine Zeit oder Ressourcen beim Warten auf die Rückgabe von E / A-Anforderungen.

In dem traditionellen Ansatz Web - Server zu erstellen, für jede eingehende Anforderung oder die Verbindung der Server laicht einen neuen Ausführungs - Thread oder sogar gabelt einen neuen Prozess die Anfrage und senden Sie eine Antwort zu handhaben . Konzeptionell ist dies durchaus sinnvoll, in der Praxis ist jedoch ein erheblicher Aufwand erforderlich.

Das Laichen von Threads verursacht zwar weniger Speicher- und CPU-Overhead als das Verzweigen von Prozessen , kann jedoch ineffizient sein. Das Vorhandensein einer großen Anzahl von Threads kann dazu führen, dass ein stark ausgelastetes System wertvolle Zyklen für die Thread-Planung und den Kontextwechsel benötigt, was die Latenz erhöht und die Skalierbarkeit und den Durchsatz einschränkt.

Node.js verfolgt einen anderen Ansatz. Es wird eine Single-Threaded-Ereignisschleife ausgeführt, die beim System registriert ist, um Verbindungen zu verarbeiten, und jede neue Verbindung führt dazu, dass eine JavaScript- Rückruffunktion ausgelöst wird . Die Rückruffunktion kann Anforderungen mit nicht blockierenden E / A-Aufrufen verarbeiten und bei Bedarf Threads aus einem Pool erzeugen, um blockierende oder CPU-intensive Vorgänge auszuführen und den Lastausgleich zwischen CPU-Kernen zu ermöglichen. Der Ansatz von Node zur Skalierung mit Rückruffunktionen erfordert weniger Speicher, um mehr Verbindungen zu verarbeiten als die meisten wettbewerbsfähigen Architekturen, die mit Threads skaliert werden, einschließlich Apache HTTP Server, den verschiedenen Java-Anwendungsservern, IIS und ASP.NET sowie Ruby on Rails.

Node.js erweist sich neben Servern auch als sehr nützlich für Desktop-Anwendungen. Beachten Sie auch, dass Knotenanwendungen nicht auf reines JavaScript beschränkt sind. Sie können jede Sprache verwenden, die sich in JavaScript umwandelt, z. B. TypeScript und CoffeeScript. Node.js enthält die JavaScript-Engine von Google Chrome V8, die die ECMAScript 2015 (ES6) -Syntax unterstützt, ohne dass ein ES6-zu-ES5-Transpiler wie Babel erforderlich ist.

Ein Großteil des Dienstprogramms von Node stammt aus seiner großen Paketbibliothek, auf die über den npmBefehl zugegriffen werden kann. NPM, der Node-Paketmanager, ist Teil der Standardinstallation von Node.js, obwohl es eine eigene Website gibt.

Einige JavaScript-Geschichte

1995 erstellte Brendan Eich, damals ein Auftragnehmer von Netscape, die JavaScript-Sprache, die in Webbrowsern ausgeführt werden kann - in 10 Tagen. JavaScript sollte ursprünglich Animationen und andere Manipulationen des Browser Document Object Model (DOM) ermöglichen. Kurz darauf wurde eine Version von JavaScript für den Netscape Enterprise Server eingeführt.

Der Name JavaScript wurde zu Marketingzwecken gewählt, da die Java-Sprache von Sun zu dieser Zeit weit verbreitet war. Tatsächlich basierte die JavaScript-Sprache hauptsächlich auf den Scheme- und Self-Sprachen mit oberflächlicher Java-ähnlicher Semantik.

Anfänglich haben viele Programmierer JavaScript als nutzlos für „echte Arbeit“ abgetan, da sein Interpreter eine Größenordnung langsamer lief als kompilierte Sprachen. Dies änderte sich, als mehrere Forschungsanstrengungen zur Beschleunigung von JavaScript Früchte trugen. Am bekanntesten ist, dass die Open-Source-JavaScript-Engine Google Chrome V8, die Just-in-Time-Kompilierung, Inlining und dynamische Codeoptimierung durchführt, C ++ - Code bei einigen Ladevorgängen tatsächlich übertrifft und Python in den meisten Anwendungsfällen übertrifft.

Die JavaScript-basierte Node.js-Plattform wurde 2009 von Ryan Dahl für Linux und MacOS als skalierbarere Alternative zum Apache HTTP Server eingeführt. NPM, geschrieben von Isaac Schlueter, wurde 2010 gestartet. Eine native Windows-Version von Node.js wurde 2011 veröffentlicht.

Joyent besaß, regierte und unterstützte die Entwicklungsbemühungen von Node.j über viele Jahre. Im Jahr 2015 wurde das Node.js-Projekt an die Node.js-Stiftung übergeben und vom technischen Lenkungsausschuss der Stiftung geleitet. Node.js wurde auch als Linux Foundation Collaborative Project aufgenommen. 2019 schlossen sich die Node.js Foundation und die JS Foundation zur OpenJS Foundation zusammen.

Grundlegende Node.js-Architektur

Auf hoher Ebene kombiniert Node.js die Google V8-JavaScript-Engine, eine nicht blockierende Ereignisschleife mit einem Thread und eine E / A-API auf niedriger Ebene. Der unten gezeigte abgespeckte Beispielcode veranschaulicht das grundlegende HTTP-Servermuster unter Verwendung von ES6-Pfeilfunktionen (anonyme Lambda-Funktionen, die mit dem Fettpfeiloperator deklariert wurden =>) für die Rückrufe.

Der Anfang des Codes lädt das HTTP-Modul, setzt die Servervariable hostnameauf localhost(127.0.0.1) und setzt die portVariable auf 3000. Anschließend werden ein Server und eine Rückruffunktion erstellt, in diesem Fall eine Fettpfeilfunktion, die immer dieselbe zurückgibt Antwort auf jede Anfrage: statusCode200 (Erfolg), Inhaltstyp Klartext und eine Textantwort von ”Hello World\n”. Schließlich weist es den Server an, localhostPort 3000 (über einen Socket) abzuhören, und definiert einen Rückruf, um eine Protokollnachricht auf der Konsole zu drucken, wenn der Server mit dem Abhören begonnen hat. Wenn Sie diesen Code mit dem nodeBefehl in einem Terminal oder einer Konsole ausführen und dann mit einem beliebigen Webbrowser auf demselben Computer zu localhost: 3000 navigieren, wird in Ihrem Browser "Hello World" angezeigt. Um den Server zu stoppen, drücken Sie im Terminalfenster Strg-C.

Beachten Sie, dass jeder in diesem Beispiel getätigte Aufruf asynchron und nicht blockierend ist. Die Rückruffunktionen werden als Reaktion auf Ereignisse aufgerufen. Der createServerRückruf behandelt ein Clientanforderungsereignis und gibt eine Antwort zurück. Der listenRückruf behandelt das listeningEreignis.

Die Node.js-Bibliothek

Wie Sie auf der linken Seite in der folgenden Abbildung sehen können, verfügt Node.js über einen großen Funktionsumfang in seiner Bibliothek. Das HTTP-Modul, das wir zuvor im Beispielcode verwendet haben, enthält sowohl Client- als auch Serverklassen, wie Sie auf der rechten Seite der Abbildung sehen können. Die HTTPS-Serverfunktionalität, die TLS oder SSL verwendet, befindet sich in einem separaten Modul.

Ein inhärentes Problem bei einer Single-Threaded-Ereignisschleife ist das Fehlen einer vertikalen Skalierung, da der Ereignisschleifen-Thread nur einen einzelnen CPU-Kern verwendet. Inzwischen legen moderne CPU-Chips häufig acht oder mehr Kerne frei, und moderne Server-Racks verfügen häufig über mehrere CPU-Chips. Eine Single-Threaded-Anwendung kann die über 24 Kerne in einem robusten Server-Rack nicht voll ausnutzen.

Sie können das beheben, obwohl zusätzliche Programmierung erforderlich ist. Zunächst kann Node.js untergeordnete Prozesse erzeugen und Pipes zwischen übergeordneten und untergeordneten Elementen verwalten, ähnlich wie der Systemaufruf popen(3)funktioniert child_process.spawn() und verwandte Methoden verwendet.

Das Cluster-Modul ist noch interessanter als das untergeordnete Prozessmodul zum Erstellen skalierbarer Server. Die cluster.fork()Methode erzeugt Worker-Prozesse, die die Server-Ports der Eltern gemeinsam nutzen, child_process.spawn()unter der Abdeckung. Der Cluster-Master verteilt eingehende Verbindungen unter seinen Mitarbeitern mithilfe eines Round-Robin-Algorithmus, der empfindlich auf die Prozesslasten der Mitarbeiter reagiert.

Beachten Sie, dass Node.js keine Routing-Logik bereitstellt. Wenn Sie den Status über Verbindungen in einem Cluster hinweg beibehalten möchten, müssen Sie Ihre Sitzungs- und Anmeldeobjekte an einem anderen Ort als dem Arbeitsspeicher aufbewahren.

Das Node.js-Paket-Ökosystem

Die NPM-Registrierung enthält mehr als 1,2 Millionen Pakete mit kostenlosem, wiederverwendbarem Node.js-Code. Damit ist sie die größte Software-Registrierung der Welt. Beachten Sie, dass die meisten NPM- Pakete (im Wesentlichen Ordner oder NPM-Registrierungselemente, die ein Programm enthalten, das durch eine package.json-Datei beschrieben wird) mehrere Module enthalten (Programme, die Sie mit requireAnweisungen laden ). Es ist leicht, die beiden Begriffe zu verwechseln, aber in diesem Zusammenhang haben sie bestimmte Bedeutungen und sollten nicht ausgetauscht werden.

NPM kann Pakete verwalten, die lokale Abhängigkeiten eines bestimmten Projekts sind, sowie global installierte JavaScript-Tools. Bei Verwendung als Abhängigkeitsmanager für ein lokales Projekt kann NPM mit einem Befehl alle Abhängigkeiten eines Projekts über die Datei package.json installieren. Bei Verwendung für globale Installationen erfordert NPM häufig Systemberechtigungen (sudo).

Sie müssen nicht haben , um die NPM - Befehlszeile verwenden , um die Öffentlichkeit NPM Registrierung zugreifen. Andere Paketmanager wie Facebooks Yarn bieten alternative Erfahrungen auf Kundenseite. Sie können auch über die NPM-Website nach Paketen suchen und suchen.

Warum sollten Sie ein NPM-Paket verwenden? In vielen Fällen ist die Installation eines Pakets über die NPM-Befehlszeile am schnellsten und bequemsten, um die neueste stabile Version eines Moduls in Ihrer Umgebung auszuführen. In der Regel ist dies weniger aufwendig als das Klonen des Quellrepositorys und das Erstellen einer Installation aus dem Repository. Wenn Sie nicht die neueste Version möchten, können Sie NPM eine Versionsnummer angeben. Dies ist besonders nützlich, wenn ein Paket von einem anderen Paket abhängt und möglicherweise mit einer neueren Version der Abhängigkeit beschädigt wird.

Das Express-Framework, ein minimales und flexibles Webanwendungsframework von Node.j, bietet beispielsweise eine Reihe robuster Funktionen zum Erstellen von ein- und mehrseitigen sowie hybriden Webanwendungen. Während sich das leicht klonbare Expresscode-Repository unter //github.com/expressjs/express befindet und sich die Express-Dokumentation unter //expressjs.com/ befindet, besteht eine schnelle Möglichkeit, Express zu verwenden, darin, es in einer bereits initialisierten lokalen Arbeitsentwicklung zu installieren Verzeichnis mit dem npmBefehl, zum Beispiel:

$ npm install express - speichern

Die —saveOption, die in NPM 5.0 und höher standardmäßig aktiviert ist, weist den Paketmanager an, das Express-Modul nach der Installation zur Abhängigkeitsliste in der Datei package.json hinzuzufügen.

Eine weitere schnelle Möglichkeit, Express zu verwenden, besteht darin, den ausführbaren Generatorexpress(1) global zu installieren und anschließend die Anwendung lokal in einem neuen Arbeitsordner zu erstellen:

$ npm install -g Express-Generator @ 4

$ express / tmp / foo && cd / tmp / foo

Wenn dies erledigt ist, können Sie NPM verwenden, um alle erforderlichen Abhängigkeiten zu installieren und den Server basierend auf dem Inhalt der vom Generator erstellten Datei package.json zu starten:

$ npm installieren

$ npm starten

Es ist schwierig, Highlights aus den über einer Million Paketen im NPM auszuwählen, aber einige Kategorien fallen auf. Express ist das älteste und bekannteste Beispiel für Node.js Frameworks. Eine weitere große Kategorie im NPM-Repository sind JavaScript-Entwicklungsdienstprogramme, darunter browserify, ein Modulbündler. bower, der Browser-Paketmanager; grunzen, der JavaScript-Task-Runner; und schlucken, das Streaming-Build-System. Eine wichtige Kategorie für Entwickler von Node.js in Unternehmen sind Datenbankclients, von denen es mehr als 8.000 gibt, darunter beliebte Module wie Redis, Mungo, Firebase und pg, der PostgreSQL-Client.

Zusammenfassend ist Node.js eine plattformübergreifende JavaScript-Laufzeitumgebung für Server und Anwendungen. Es basiert auf einer nicht blockierenden Ereignisschleife mit einem Thread, der JavaScript-Engine von Google Chrome V8 und einer E / A-API auf niedriger Ebene. Verschiedene Techniken, einschließlich des Cluster-Moduls, ermöglichen es Node.js Apps, über einen einzelnen CPU-Kern hinaus zu skalieren. Über seine Kernfunktionalität hinaus hat Node.js ein Ökosystem von mehr als einer Million Paketen inspiriert, die im NPM-Repository registriert und versioniert sind und über die NPM-Befehlszeile oder eine Alternative wie Yarn installiert werden können.