Was ist Node.js? [geschlossen]


506

Ich verstehe nicht ganz, worum es bei Node.js geht. Vielleicht liegt es daran, dass ich hauptsächlich ein webbasierter Entwickler von Geschäftsanwendungen bin. Was ist es und wozu dient es?

Mein bisheriges Verständnis ist:

  1. Das Programmiermodell ist ereignisgesteuert, insbesondere die Art und Weise, wie es mit E / A umgeht .
  2. Es verwendet JavaScript und der Parser ist V8 .
  3. Es kann leicht verwendet werden, um gleichzeitige Serveranwendungen zu erstellen.

Sind meine Erkenntnisse richtig? Wenn ja, was sind dann die Vorteile von Evented I / O, ist es nur mehr für die Parallelität? Ist die Richtung von Node.js auch ein Framework wie ein JavaScript-basiertes (V8-basiertes) Programmiermodell?

Antworten:


213

Ich denke, die Vorteile sind:

  1. Webentwicklung in einer dynamischen Sprache (JavaScript) auf einer unglaublich schnellen VM (V8). Es ist viel schneller als Ruby, Python oder Perl.

  2. Fähigkeit, Tausende von gleichzeitigen Verbindungen mit minimalem Overhead in einem einzigen Prozess zu verarbeiten.

  3. JavaScript ist perfekt für Ereignisschleifen mit erstklassigen Funktionsobjekten und Abschlüssen. Die Leute wissen bereits, wie man es auf diese Weise benutzt, nachdem sie es im Browser verwendet haben, um auf vom Benutzer initiierte Ereignisse zu reagieren.

  4. Viele Leute kennen JavaScript bereits, auch Leute, die nicht behaupten, Programmierer zu sein. Es ist wohl die beliebteste Programmiersprache.

  5. Die Verwendung von JavaScript auf einem Webserver sowie im Browser verringert die Impedanzfehlanpassung zwischen den beiden Programmierumgebungen, die Datenstrukturen über JSON kommunizieren können, die auf beiden Seiten der Gleichung gleich funktionieren. Doppelter Formularüberprüfungscode kann zwischen Server und Client usw. gemeinsam genutzt werden.


1
@postfuturist: Es funktioniert tatsächlich gut gegen viele Alternativen. In vielen Fällen schlägt es Java 6 auch ziemlich handlich. Ordentlich!
Adam Crossland

1
@postfuturist Ich denke du hast gegen Java 6 -Xint verglichen. Versuchen Sie, mit Java 6-Server
Fedesilva

@iJK yammer.com ist eine funktionierende Anwendung von node.js
Gerard Banasig

1
Komisch, ich habe vor 10 Jahren JScript in ASP geschrieben, um (a) die Schrecklichkeit von VBScript zu vermeiden, (b) dieselbe Sprache auf dem Client und Server zu verwenden und (c) meine eigenen und die JS-Bibliotheken anderer wiederzuverwenden für die Handhabung von Saiten ... usw.
Antony Quinn

4
@Warum hast du diesen Beitrag nur für "Legacy Bullshit" bearbeitet? Ich glaube nicht, dass 212 Leute für diesen Beitrag gestimmt hätten, wenn Sie dies von Anfang an geschrieben hätten.
Julien Fouilhé

619

Ich benutze Node.js bei der Arbeit und finde es sehr mächtig. Ich würde gezwungen sein, ein Wort zu wählen, um Node.js zu beschreiben, und würde "interessant" sagen (was kein rein positives Adjektiv ist). Die Community ist lebendig und wächst. JavaScript kann trotz seiner Kuriositäten eine großartige Sprache zum Codieren sein. Und Sie werden täglich Ihr eigenes Verständnis von "Best Practice" und den Mustern von gut strukturiertem Code überdenken. Momentan fließt eine enorme Energie von Ideen in Node.js, und wenn Sie daran arbeiten, sind Sie all diesem Denken ausgesetzt - großartigem mentalem Gewichtheben.

Node.js in der Produktion ist definitiv möglich, aber weit entfernt von der "schlüsselfertigen" Bereitstellung, die in der Dokumentation anscheinend versprochen wird. Mit Node.js v0.6.x wurde "Cluster" in die Plattform integriert und stellt einen der wesentlichen Bausteine ​​dar. Mein "Production.js" -Skript enthält jedoch immer noch ~ 150 Logikzeilen, um Dinge wie das Erstellen des Protokolls zu erledigen Verzeichnis, Recycling toter Arbeiter usw. Für einen "ernsthaften" Produktionsservice müssen Sie auch darauf vorbereitet sein, eingehende Verbindungen zu drosseln und all die Dinge zu erledigen, die Apache für PHP erledigt . Um fair zu sein, hat Ruby on Rails genau dieses Problem. Es wird über zwei komplementäre Mechanismen gelöst: 1) Ruby auf Schienen / Knoten setzen.Apache / Lighttd ). Der Webserver kann statische Inhalte effizient bereitstellen, auf die Protokollierung zugreifen, URLs neu schreiben, SSL beenden , Zugriffsregeln durchsetzen und mehrere Unterdienste verwalten. Bei Anforderungen, die den eigentlichen Knotendienst erfüllen, leitet der Webserver die Anforderung weiter. 2) Verwenden eines Frameworks wie Unicorn , das die Arbeitsprozesse verwaltet, sie regelmäßig recycelt usw. Ich habe noch kein Node.js-Serving-Framework gefunden, das vollständig gebacken zu sein scheint. es mag existieren, aber ich habe es noch nicht gefunden und verwende immer noch ~ 150 Zeilen in meiner handgerollten "Production.js".

Das Lesen von Frameworks wie Express lässt den Eindruck entstehen, dass die Standardpraxis darin besteht, alles über einen einzigen Node.js-Service zu bedienen ... "app.use (express.static (__ dirname + '/ public'))" . Für Dienste und Entwicklungen mit geringerer Auslastung ist dies wahrscheinlich in Ordnung. Sobald Sie jedoch versuchen, Ihren Service zeitaufwändig zu belasten und ihn rund um die Uhr laufen zu lassen, werden Sie schnell die Motive entdecken, die große Websites dazu veranlassen, gut gebackenen, gehärteten C-Code wie Nginx auf ihre Website zu setzen und alle zu verwalten der statischen Inhaltsanforderungen (... bis Sie ein CDN wie Amazon CloudFront einrichten )). Für eine etwas humorvolle und unverfroren negative Einstellung sehen Sie diesen Kerl .

Node.js findet auch immer mehr Nicht-Service-Anwendungen. Selbst wenn Sie etwas anderes zum Bereitstellen von Webinhalten verwenden, können Sie Node.js als Build-Tool verwenden, indem Sie Ihren Code mit npm- Modulen organisieren, mit Browserify in ein einzelnes Asset zusammenfügen und mit uglify-js für die Bereitstellung minimieren . Für den Umgang mit dem Web ist JavaScript eine perfekte Impedanzanpassung und häufig die einfachste Angriffsroute. Wenn Sie beispielsweise eine Reihe von JSON- Antwortnutzdaten durchsuchen möchten , sollten Sie mein Unterstrich-CLI- Modul verwenden, das Dienstprogramm für strukturierte Daten.

Für und Wider:

  • Pro: Für einen Server-Typ war das Schreiben von JavaScript im Backend eine "Einstiegsdroge" zum Erlernen moderner UI-Muster. Ich habe keine Angst mehr, Client-Code zu schreiben.
  • Pro: Neigt dazu, eine ordnungsgemäße Fehlerprüfung zu fördern (err wird von praktisch allen Rückrufen zurückgegeben, was den Programmierer dazu zwingt, damit umzugehen). Außerdem behandeln async.js und andere Bibliotheken das Paradigma "Fehler, wenn eine dieser Unteraufgaben fehlschlägt" viel besser als typischer synchroner Code )
  • Pro: Einige interessante und normalerweise schwierige Aufgaben werden trivial - wie das Abrufen des Status von Aufgaben im Flug, die Kommunikation zwischen Mitarbeitern oder das Teilen des Cache-Status
  • Pro: Riesige Community und jede Menge großartiger Bibliotheken basierend auf einem soliden Paketmanager (npm)
  • Con: JavaScript hat keine Standardbibliothek. Sie sind so an das Importieren von Funktionen gewöhnt, dass es sich komisch anfühlt, wenn Sie JSON.parse oder eine andere integrierte Methode verwenden, für die kein npm-Modul hinzugefügt werden muss. Dies bedeutet, dass es von allem fünf Versionen gibt. Sogar die im "Kern" von Node.j enthaltenen Module haben fünf weitere Varianten, falls Sie mit der Standardimplementierung nicht zufrieden sind. Dies führt zu einer raschen Entwicklung, aber auch zu einer gewissen Verwirrung.

Im Vergleich zu einem einfachen One-Process-per-Request-Modell ( LAMP ):

  • Pro: Skalierbar auf Tausende von aktiven Verbindungen. Sehr schnell und sehr effizient. Für eine Webflotte könnte dies eine 10-fache Reduzierung der Anzahl der erforderlichen Boxen im Vergleich zu PHP oder Ruby bedeuten
  • Pro: Das Schreiben paralleler Muster ist einfach. Stellen Sie sich vor, Sie müssen drei (oder N) Blobs aus Memcached abrufen . Tun Sie dies in PHP ... haben Sie gerade Code geschrieben, der den ersten Blob abruft, dann den zweiten, dann den dritten? Wow, das ist langsam. Es gibt ein spezielles PECL- Modul, um dieses spezielle Problem für Memcached zu beheben. Was ist jedoch, wenn Sie einige Memcached-Daten parallel zu Ihrer Datenbankabfrage abrufen möchten? In Node.js ist es sehr natürlich, dass eine Webanforderung mehrere Dinge parallel ausführt, da das Paradigma asynchron ist.
  • Con: Asynchroner Code ist grundlegend komplexer als synchroner Code, und die Lernkurve im Voraus kann für Entwickler schwierig sein, ohne genau zu verstehen, was gleichzeitige Ausführung tatsächlich bedeutet. Trotzdem ist es weitaus weniger schwierig, Multithread-Code mit Sperre zu schreiben.
  • Con: Wenn eine rechenintensive Anforderung beispielsweise 100 ms lang ausgeführt wird, blockiert sie die Verarbeitung anderer Anforderungen, die im selben Node.js-Prozess verarbeitet werden ... AKA, Cooperative-Multitasking . Dies kann durch das Web Workers-Muster (Ausgliedern eines Unterprozesses zur Bewältigung der teuren Aufgabe) verringert werden. Alternativ können Sie eine große Anzahl von Node.js-Workern verwenden und nur einen einzelnen gleichzeitig bearbeiten lassen (immer noch ziemlich effizient, da kein Prozessrecycling erfolgt).
  • Con: Das Ausführen eines Produktionssystems ist VIEL komplizierter als ein CGI- Modell wie Apache + PHP, Perl , Ruby usw. Nicht behandelte Ausnahmen führen zu einer Unterbrechung des gesamten Prozesses und erfordern eine Logik zum Neustart fehlgeschlagener Worker (siehe Cluster ). Module mit fehlerhaftem nativem Code können den Prozess zum Absturz bringen. Wenn ein Mitarbeiter stirbt, werden alle von ihm bearbeiteten Anforderungen gelöscht, sodass eine fehlerhafte API den Service für andere kohostierte APIs leicht beeinträchtigen kann.

Im Gegensatz zum Schreiben eines "echten" Dienstes in Java / C # / C (C? Wirklich?)

  • Pro: Asynchron in Node.js zu arbeiten ist einfacher als Thread-Sicherheit an anderer Stelle und bietet wahrscheinlich einen größeren Nutzen. Node.js ist bei weitem das am wenigsten schmerzhafte asynchrone Paradigma, an dem ich je gearbeitet habe. Mit guten Bibliotheken ist es nur geringfügig schwieriger als das Schreiben von synchronem Code.
  • Pro: Keine Multithreading / Locking-Fehler. Richtig, Sie investieren im Voraus in das Schreiben von ausführlicherem Code, der einen ordnungsgemäßen asynchronen Workflow ohne Blockierungsvorgänge ausdrückt. Und Sie müssen einige Tests schreiben und das Ding zum Laufen bringen (es ist eine Skriptsprache und fette Fingervariablennamen werden nur zur Zeit des Unit-Tests abgefangen). ABER, sobald Sie es zum Laufen bringen , ist die Oberfläche für Heisenbugs - seltsame Probleme, die sich nur einmal in einer Million Läufen manifestieren - diese Oberfläche nur viel viel kleiner . Die Steuern, die Node.js Code schreiben, werden stark in die Codierungsphase vorab geladen. Dann neigen Sie dazu, stabilen Code zu erhalten.
  • Pro: JavaScript ist viel einfacher, um Funktionen auszudrücken. Es ist schwer, dies mit Worten zu beweisen, aber JSON , dynamische Typisierung, Lambda-Notation, prototypische Vererbung, leichte Module, was auch immer ... es braucht nur weniger Code, um die gleichen Ideen auszudrücken.
  • Con: Vielleicht mögen Sie Codierungsdienste in Java wirklich, wirklich?

Eine weitere Perspektive zu JavaScript und Node.js finden Sie unter Von Java zu Node.js , einem Blogbeitrag über die Eindrücke und Erfahrungen eines Java-Entwicklers beim Erlernen von Node.js.


Module Wenn der Knoten unter Berücksichtigung, bedenken Sie, dass Ihre Wahl von JavaScript - Bibliotheken werden DEFINE Ihre Erfahrungen. Die meisten Benutzer verwenden mindestens zwei, einen asynchronen Musterhelfer (Step, Futures, Async) und ein JavaScript-Zuckermodul ( Underscore.js ).

Helfer / JavaScript Sugar:

  • Underscore.js - benutze dies. TU es einfach. Es macht Ihren Code schön und lesbar mit Sachen wie _.isString () und _.isArray (). Ich bin mir nicht sicher, wie Sie sonst sicheren Code schreiben könnten. Weitere Informationen zur erweiterten Befehlszeilenfunktion finden Sie in meiner eigenen Unterstrich-CLI .

Asynchrone Mustermodule:

  • Schritt - eine sehr elegante Art, Kombinationen von seriellen und parallelen Aktionen auszudrücken. Meine persönliche Empfehlung. In meinem Beitrag erfahren Sie, wie der Schrittcode aussieht.
  • Futures - viel flexibler (ist das wirklich eine gute Sache?), Um Bestellungen durch Anforderungen auszudrücken. Kann Dinge wie "a, b, c parallel starten. Wenn A und B fertig sind, starten Sie AB. Wenn A und C fertig sind, starten Sie AC." Diese Flexibilität erfordert mehr Sorgfalt, um Fehler in Ihrem Workflow zu vermeiden (z. B. niemals oder mehrmals aufrufen). Siehe Raynos 'Beitrag über die Verwendung von Futures (dies ist der Beitrag, der mich dazu gebracht hat, Futures zu "bekommen").
  • Async - traditionellere Bibliothek mit einer Methode für jedes Muster. Ich begann damit vor meiner religiösen Bekehrung zum Schritt und der anschließenden Erkenntnis, dass alle Muster in Async in Schritt mit einem einzigen besser lesbaren Paradigma ausgedrückt werden könnten.
  • TameJS - Geschrieben von OKCupid, ist es ein Precompiler, der ein neues Sprachprimativ "Warten" hinzufügt, um elegant serielle und parallele Workflows zu schreiben. Das Muster sieht toll aus, erfordert aber eine Vorkompilierung. Ich entscheide mich immer noch für diesen einen.
  • StreamlineJS - Konkurrent von TameJS. Ich neige mich zu Tame, aber Sie können sich selbst entscheiden.

Um alles über die asynchronen Bibliotheken zu lesen, lesen Sie dieses Panel-Interview mit den Autoren.

Web Framework:

  • Express Great Ruby on Rails-esk-Framework zum Organisieren von Websites. Es verwendet JADE als XML / HTML-Template-Engine, wodurch das Erstellen von HTML weitaus weniger schmerzhaft und sogar fast elegant wird.
  • jQuery Obwohl jQuery technisch gesehen kein Knotenmodul ist, entwickelt es sich schnell zu einem De-facto-Standard für die clientseitige Benutzeroberfläche. jQuery bietet CSS-ähnliche Selektoren zum Abfragen von Gruppen von DOM-Elementen, die dann bearbeitet werden können (Gruppenhandler, Eigenschaften, Stile usw.). Entsprechend dem Bootstrap- CSS-Framework von Twitter , Backbone.js für ein MVC- Muster und Browserify.js , um alle Ihre JavaScript-Dateien zu einer einzigen Datei zusammenzufügen. Diese Module werden alle zu De-facto-Standards, daher sollten Sie sie zumindest überprüfen, wenn Sie noch nichts davon gehört haben.

Testen:

  • JSHint - Muss verwendet werden; Ich habe das zunächst nicht benutzt, was jetzt unverständlich erscheint. JSLint fügt eine Reihe grundlegender Überprüfungen zurück, die Sie mit einer kompilierten Sprache wie Java erhalten. Nicht übereinstimmende Klammern, nicht deklarierte Variablen, Tippfehler in vielen Formen und Größen. Sie können auch verschiedene Formen des sogenannten "Anal-Modus" aktivieren, in dem Sie den Stil von Leerzeichen und so weiter überprüfen. Dies ist in Ordnung, wenn dies Ihre Tasse Tee ist. Der wahre Wert ergibt sich jedoch aus der sofortigen Rückmeldung der genauen Zeilennummer Sie haben ein schließendes ")" vergessen ... ohne Ihren Code ausführen und die beleidigende Zeile treffen zu müssen. „JSHint“ ist eine konfigurierbare Variante von Douglas Crockford ‚s JSLint .
  • Mokka- Konkurrent zu Gelübden, die ich allmählich bevorzuge. Beide Frameworks beherrschen die Grundlagen gut genug, aber komplexe Muster lassen sich in Mocha leichter ausdrücken.
  • Gelübde Gelübde sind wirklich sehr elegant. Und es druckt einen schönen Bericht (--spec) aus, der Ihnen zeigt, welche Testfälle bestanden / nicht bestanden wurden. Nehmen Sie sich 30 Minuten Zeit, um es zu lernen, und Sie können mit minimalem Aufwand grundlegende Tests für Ihre Module erstellen.
  • Zombie - Kopfloses Testen auf HTML und JavaScript mit JSDom als virtuellem "Browser". Sehr mächtiges Zeug. Kombinieren Sie es mit Replay , um blitzschnelle deterministische Tests des Codes im Browser zu erhalten.
  • Ein Kommentar zum "Nachdenken" über Tests:
    • Das Testen ist nicht optional. Bei einer dynamischen Sprache wie JavaScript gibt es nur sehr wenige statische Überprüfungen. Wenn Sie beispielsweise zwei Parameter an eine Methode übergeben, die 4 erwartet, wird dies erst unterbrochen, wenn der Code ausgeführt wird. Ziemlich niedriger Balken zum Erstellen von Fehlern in JavaScript. Grundlegende Tests sind wichtig, um die Überprüfungslücke mit kompilierten Sprachen zu schließen.
    • Vergessen Sie die Validierung, lassen Sie einfach Ihren Code ausführen. Für jede Methode ist mein erster Validierungsfall "nichts bricht", und das ist der Fall, der am häufigsten ausgelöst wird. Wenn Sie beweisen, dass Ihr Code ohne Auslösen ausgeführt wird, werden 80% der Fehler abgefangen und Ihr Code-Vertrauen wird so stark verbessert, dass Sie zurückkehren und die übersprungenen nuancierten Validierungsfälle hinzufügen.
    • Fangen Sie klein an und brechen Sie die Trägheitsbarriere. Wir sind alle faul und unter Zeitdruck, und das Testen ist leicht als "zusätzliche Arbeit" anzusehen. Fangen Sie also klein an. Schreiben Sie Testfall 0 - laden Sie Ihr Modul und melden Sie den Erfolg. Wenn Sie sich dazu zwingen, genau so viel zu tun, ist die Trägheitsbarriere für Tests durchbrochen. Das sind <30 Minuten, um es zum ersten Mal zu tun, einschließlich des Lesens der Dokumentation. Schreiben Sie nun Testfall 1 - rufen Sie eine Ihrer Methoden auf und vergewissern Sie sich, dass "nichts kaputt geht", dh dass Sie keinen Fehler zurückerhalten. Testfall 1 sollte weniger als eine Minute dauern. Wenn die Trägheit weg ist, ist es einfach, Ihre Testabdeckung schrittweise zu erweitern.
    • Entwickeln Sie jetzt Ihre Tests mit Ihrem Code. Lassen Sie sich nicht einschüchtern, wie der "richtige" End-to-End-Test mit Mock-Servern und all dem aussehen würde. Code beginnt einfach und entwickelt sich, um neue Fälle zu behandeln. Tests sollten auch. Wenn Sie Ihrem Code neue Fälle und neue Komplexität hinzufügen, fügen Sie Testfälle hinzu, um den neuen Code auszuführen. Wenn Sie Fehler finden, fügen Sie Überprüfungen und / oder neue Fälle hinzu, um den fehlerhaften Code abzudecken. Wenn Sie debuggen und das Vertrauen in einen Code verlieren, gehen Sie zurück und fügen Sie Tests hinzu, um zu beweisen, dass er das tut, was Sie denken. Erfassen Sie Zeichenfolgen von Beispieldaten (von anderen Diensten, die Sie aufrufen, Websites, die Sie kratzen, was auch immer) und geben Sie sie an Ihren Parsing-Code weiter. In einigen Fällen wurde die Validierung dort verbessert, und Sie erhalten einen äußerst zuverlässigen Code.

Lesen Sie auch die offizielle Liste der empfohlenen Node.js-Module. Das Node Modules Wiki von GitHub ist jedoch viel vollständiger und eine gute Ressource.


Um Node zu verstehen, ist es hilfreich, einige der wichtigsten Designoptionen zu berücksichtigen:

Node.js ist EVENT -BASIERT und ASYNCHRON / NON-BLOCKING. Ereignisse wie eine eingehende HTTP-Verbindung lösen eine JavaScript-Funktion aus, die ein wenig Arbeit erledigt und andere asynchrone Aufgaben wie das Herstellen einer Verbindung zu einer Datenbank oder das Abrufen von Inhalten von einem anderen Server startet. Sobald diese Aufgaben gestartet wurden, wird die Ereignisfunktion beendet und Node.js wird wieder in den Ruhezustand versetzt. Sobald etwas anderes passiert, z. B. die Herstellung der Datenbankverbindung oder der externe Server, der mit Inhalten antwortet, werden die Rückruffunktionen ausgelöst und mehr JavaScript-Code ausgeführt, wodurch möglicherweise noch mehr asynchrone Aufgaben (wie eine Datenbankabfrage) ausgelöst werden. Auf diese Weise verschachtelt Node.js gerne Aktivitäten für mehrere parallele Workflows und führt alle Aktivitäten aus, die zu einem beliebigen Zeitpunkt nicht blockiert sind. Aus diesem Grund leistet Node.js hervorragende Arbeit bei der Verwaltung von Tausenden von gleichzeitigen Verbindungen.

Warum nicht wie alle anderen auch nur einen Prozess / Thread pro Verbindung verwenden?In Node.js ist eine neue Verbindung nur eine sehr kleine Heap-Zuordnung. Das Hochfahren eines neuen Prozesses benötigt erheblich mehr Speicher, auf einigen Plattformen ein Megabyte. Die tatsächlichen Kosten sind jedoch die mit dem Kontextwechsel verbundenen Gemeinkosten. Wenn Sie 10 ^ 6 Kernel-Threads haben, muss der Kernel viel Arbeit leisten, um herauszufinden, wer als nächstes ausgeführt werden soll. Es wurde viel Arbeit in die Erstellung eines O (1) -Planers für Linux gesteckt, aber am Ende ist es viel effizienter, einen einzelnen ereignisgesteuerten Prozess zu haben, als 10 ^ 6 Prozesse, die um die CPU-Zeit konkurrieren. Unter Überlastungsbedingungen verhält sich das Multiprozessmodell außerdem sehr schlecht und es fehlen wichtige Verwaltungs- und Verwaltungsdienste, insbesondere SSHD (was bedeutet, dass Sie sich nicht einmal in die Box einloggen können, um herauszufinden, wie geschraubt es wirklich ist).

Node.js ist SINGLE THREADED und LOCK FREE . Node.js hat als sehr bewusste Designauswahl nur einen einzigen Thread pro Prozess. Aus diesem Grund ist es grundsätzlich unmöglich, dass mehrere Threads gleichzeitig auf Daten zugreifen. Somit werden keine Schlösser benötigt. Fäden sind hart. Wirklich sehr, sehr schwer. Wenn Sie das nicht glauben, haben Sie nicht genug Thread-Programmierung durchgeführt. Das richtige Sperren ist schwierig und führt zu Fehlern, die wirklich schwer zu finden sind. Durch das Eliminieren von Sperren und Multithreading verschwindet eine der schlimmsten Fehlerklassen. Dies könnte der größte Vorteil des Knotens sein.

Aber wie nutze ich meine 16-Core-Box?

Zwei Wege:

  1. Für große, schwere Rechenaufgaben wie die Bildcodierung kann Node.js untergeordnete Prozesse starten oder Nachrichten an zusätzliche Arbeitsprozesse senden. In diesem Entwurf muss ein Thread den Ablauf von Ereignissen und N Prozessen verwalten, die schwere Rechenaufgaben ausführen und die anderen 15 CPUs zerkauen.
  2. Um den Durchsatz auf einem Webservice zu skalieren, sollten Sie mehrere Node.js-Server auf einer Box ausführen, einen pro Kern, und dabei Cluster verwenden (Mit Node.js v0.6.x ersetzt das hier verlinkte offizielle "Cluster" -Modul die Learnboost-Version, die vorhanden ist eine andere API). Diese lokalen Node.js-Server können dann auf einem Socket konkurrieren, um neue Verbindungen zu akzeptieren und die Last über diese zu verteilen. Sobald eine Verbindung akzeptiert wird, wird sie eng an einen dieser gemeinsamen Prozesse gebunden. Theoretisch klingt das schlecht, aber in der Praxis funktioniert es recht gut und ermöglicht es Ihnen, die Kopfschmerzen beim Schreiben von thread-sicherem Code zu vermeiden. Dies bedeutet auch, dass Node.js eine hervorragende CPU-Cache-Affinität erhält und die Speicherbandbreite effektiver nutzt.

Mit Node.js können Sie einige wirklich mächtige Dinge tun, ohne ins Schwitzen zu geraten. Angenommen, Sie haben ein Node.js-Programm, das eine Vielzahl von Aufgaben ausführt, einen TCP- Port auf Befehle überwacht und einige Bilder codiert, was auch immer. Mit fünf Codezeilen können Sie ein HTTP-basiertes Webverwaltungsportal hinzufügen, das den aktuellen Status aktiver Aufgaben anzeigt. Dies ist EINFACH zu tun:

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end(myJavascriptObject.getSomeStatusInfo());
}).listen(1337, "127.0.0.1");

Jetzt können Sie eine URL eingeben und den Status Ihres laufenden Prozesses überprüfen. Wenn Sie einige Schaltflächen hinzufügen, haben Sie ein "Verwaltungsportal". Wenn Sie ein laufendes Perl / Python / Ruby-Skript haben, ist es nicht ganz einfach, nur ein Verwaltungsportal einzurichten.

Aber ist JavaScript nicht langsam / schlecht / böse / Spawn-of-the-Devil? JavaScript hat einige seltsame Kuriositäten, aber mit "den guten Teilen" gibt es dort eine sehr mächtige Sprache, und auf jeden Fall ist JavaScript DIE Sprache auf dem Client (Browser). JavaScript ist hier, um zu bleiben; Andere Sprachen zielen darauf als IL ab, und Weltklasse-Talente konkurrieren um die Entwicklung der fortschrittlichsten JavaScript-Engines. Aufgrund der Rolle von JavaScript im Browser wird ein enormer technischer Aufwand betrieben, um JavaScript schnell zum Laufen zu bringen. V8ist die neueste und beste Javascript-Engine, zumindest für diesen Monat. Die anderen Skriptsprachen werden sowohl in Bezug auf Effizienz als auch in Bezug auf Stabilität (Sie sehen sich an, Ruby) umgehauen. Und es wird nur besser, wenn große Teams bei Microsoft, Google und Mozilla an dem Problem arbeiten und um die beste JavaScript-Engine konkurrieren (es ist kein JavaScript- "Interpreter" mehr, da alle modernen Engines Tonnen von JIT ausführenKompilieren unter der Haube mit Interpretation nur als Fallback für einmal ausgeführten Code). Ja, wir alle wünschen uns, wir könnten einige der seltsameren JavaScript-Sprachoptionen korrigieren, aber es ist wirklich nicht so schlimm. Und die Sprache ist so verdammt flexibel, dass Sie wirklich kein JavaScript codieren, sondern Step oder jQuery - mehr als jede andere Sprache definieren die Bibliotheken in JavaScript die Erfahrung. Um Webanwendungen zu erstellen, müssen Sie ohnehin JavaScript kennen, sodass das Codieren auf dem Server eine Art Synergie von Fähigkeiten bietet. Ich habe mich nicht davor gefürchtet, Client-Code zu schreiben.

Wenn Sie JavaScript WIRKLICH hassen, können Sie außerdem syntaktischen Zucker wie CoffeeScript verwenden . Oder irgendetwas anderes, das JavaScript-Code erstellt, wie das Google Web Toolkit (GWT).

Apropos JavaScript, was ist ein "Abschluss"? - Eine ziemlich ausgefallene Art zu sagen, dass Sie Variablen mit lexikalischem Gültigkeitsbereich über Anrufketten hinweg beibehalten. ;) So was:

var myData = "foo";
database.connect( 'user:pass', function myCallback( result ) {
    database.query("SELECT * from Foo where id = " + myData);
} );
// Note that doSomethingElse() executes _BEFORE_ "database.query" which is inside a callback
doSomethingElse();

Sehen Sie, wie Sie "myData" einfach verwenden können, ohne etwas Unangenehmes zu tun, wie es in einem Objekt zu verstecken? Und anders als in Java muss die Variable "myData" nicht schreibgeschützt sein. Diese leistungsstarke Sprachfunktion macht die asynchrone Programmierung weniger ausführlich und weniger schmerzhaft.

Das Schreiben von asynchronem Code wird immer komplexer sein als das Schreiben eines einfachen Single-Threaded-Skripts. Mit Node.js ist es jedoch nicht viel schwieriger und Sie erhalten neben der Effizienz und Skalierbarkeit für Tausende von gleichzeitigen Verbindungen viele Vorteile. ..


"Die Variable 'myData' muss nicht schreibgeschützt sein" - anscheinend möchten Sie sie die meiste Zeit unveränderlich lassen, um Parallelitätsprobleme zu vermeiden, oder?
Nick

1
@ Nick - das ist falsch. "Parallelitätsprobleme" werden durch die Tatsache gemindert, dass der Knoten Single-Threaded ist. Das Sperren im Knoten existiert einfach nicht. Es wird in einem Single-Thread-Paradigma nicht benötigt.
Dave Dopson


1
ps, Randnotiz - Ich habe es tatsächlich so oft bearbeitet, dass der Beitrag zum "Community-Wiki" wurde (der Schwellenwert liegt bei 10 Änderungen). Ich dachte fälschlicherweise, dies sei eine Art Ehre, wenn es tatsächlich nur den Reputationsgewinn durch Upvotes blockiert. Schließlich klickte einer der Wähler vor dem CW-Status auf "Nicht abstimmen" (hoffentlich aus Versehen :) und ich verlor den Ruf ... verwirrt Ich reichte meta.stackexchange.com/questions/129941/… ein und wurde in welcher "Community" geschult Wiki "bedeutet eigentlich. Mods waren so freundlich, den CW-Status zu entfernen. :)
Dave Dopson

1
@ John - mein Debugging-Kommentar gilt absolut auch für Vanilla Asnyc. Um das Debuggen zu unterbrechen, muss ich nur einen Funktionsaufruf in "process.nextTick (...)" einschließen. Wenn es dann geworfen wird, beginnt meine Stapelverfolgung mit process.nextTick; nicht so hilfreich. Was ich wirklich wissen möchte ist: "Welcher Stapel hat process.nextTick geplant?" Ich nenne diese Daten "Kausalketten" und sie erinnern mich an 'hervorgerufen durch' bei der Behandlung von Java-Ausnahmen ... Code auf niedriger Ebene, Code auf mittlerer Ebene fängt die LL-Ausnahme ab und löst FrameworkMethodFailedException aus - ohne 'verursacht durch', den Stapel aus dem LL Code würde verloren gehen.
Dave Dopson

85

V8 ist eine Implementierung von JavaScript. Hiermit können Sie (unter anderem) eigenständige JavaScript-Anwendungen ausführen.

Node.js ist einfach eine für V8 geschriebene Bibliothek, die ereignisgesteuerte E / A ausführt. Dieses Konzept ist etwas schwieriger zu erklären, und ich bin sicher, dass jemand mit einer besseren Erklärung antworten wird als ich ... Das Wesentliche ist, dass Sie einfach nicht warten , anstatt Eingaben oder Ausgaben vorzunehmen und darauf zu warten, dass dies geschieht damit es zu Ende ist. Fragen Sie beispielsweise nach der zuletzt bearbeiteten Zeit einer Datei:

// Pseudo code
stat( 'somefile' )

Dies kann einige Millisekunden oder Sekunden dauern. Mit ereignisgesteuerter E / A lösen Sie einfach die Anforderung aus und fügen statt zu warten einen Rückruf hinzu, der ausgeführt wird, wenn die Anforderung abgeschlossen ist:

// Pseudo code
stat( 'somefile', function( result ) {
  // Use the result here
} );
// ...more code here

Dies ähnelt dem JavaScript-Code im Browser (z. B. mit Funktionen im Ajax- Stil).

Weitere Informationen finden Sie in dem Artikel Node.js, der wirklich aufregend ist und meine Einführung in die Bibliothek / Plattform war. Ich fand ihn ziemlich gut.


4
Wie wird Evented IO implementiert, ohne Sperren, Threading, Prozesse und Abschlüsse zu verwenden? Und ich habe das Gefühl, dass die Konzepte denen der funktionalen Programmierung und von Erlang ziemlich ähnlich sind.
Jeff

1
Soweit ich weiß, ist es als einfache Ereignisschleife implementiert. v8 verfügt bereits über die Callback / etc-Funktionalität, genau wie jede Javascript-Implementierung.
Rfunduk

2
Die E / A-Ereignisschleife von node.js bedeutet, dass zu einem bestimmten Zeitpunkt höchstens eine Sache ausgeführt wird. Ich sehe zwei signifikante Vorteile: Es gibt keinen Overhead beim Thread-Switching, daher ist node.js sehr schnell und zweitens sind viele typische Parallelitätsfehler, für die Java berüchtigt ist, nicht möglich.
Nalply

1
"Wie wird Evented IO implementiert, ohne ... Closures zu verwenden?" JavaScript unterstützt Schließungen und sie werden ständig in node.js verwendet (anonyme Funktionen und im Beispiel hier).
Panzi

@panzi: Ich habe nicht bemerkt, dass Jeffrey Verschlüsse in seine Liste der Dinge aufgenommen hat. node.js ist 'ohne' implementiert. Offensichtlich ist jede Funktion in Javascript eine Schließung um ihren Umfang :)
Rfunduk

35

Node.js ist ein Open Source-Befehlszeilentool, das für den serverseitigen JavaScript-Code entwickelt wurde. Sie können einen Tarball herunterladen , die Quelle kompilieren und installieren. Damit können Sie JavaScript-Programme ausführen.

Das JavaScript wird von V8 ausgeführt , einer von Google entwickelten JavaScript-Engine, die im Chrome- Browser verwendet wird. Es verwendet eine JavaScript-API, um auf das Netzwerk und das Dateisystem zuzugreifen.

Es ist beliebt für seine Leistung und die Fähigkeit, parallele Operationen durchzuführen.

Das Verständnis von node.js ist die beste Erklärung für node.js, die ich bisher gefunden habe.

Es folgen einige gute Artikel zum Thema.


13

Die Abschlüsse sind eine Möglichkeit, Code in dem Kontext auszuführen, in dem er erstellt wurde.

Für die Übereinstimmung bedeutet dies, dass Sie Variablen definieren, dann eine nicht blockierende E / A- Funktion initiieren und ihr eine anonyme Funktion für ihren Rückruf senden können.

Wenn die Aufgabe abgeschlossen ist, wird die Rückruffunktion im Kontext mit den Variablen ausgeführt. Dies ist der Abschluss.

Der Grund, warum Schließungen für das Schreiben von Anwendungen mit nicht blockierenden E / A so gut sind, ist, dass es sehr einfach ist, den Kontext von Funktionen zu verwalten, die asynchron ausgeführt werden.


8

Zwei gute Beispiele beziehen sich darauf, wie Sie Vorlagen verwalten und progressive Verbesserungen damit verwenden. Sie benötigen nur ein paar leichte Teile des JavaScript-Codes, damit es perfekt funktioniert.

Ich empfehle Ihnen dringend, diese Artikel anzuschauen und zu lesen:

Wählen Sie eine beliebige Sprache aus und versuchen Sie sich zu merken, wie Sie Ihre HTML-Dateivorlagen verwalten und was Sie tun müssen, um einen einzelnen CSS- Klassennamen in Ihrer DOM- Struktur zu aktualisieren (z. B. hat ein Benutzer auf einen Menüpunkt geklickt und diesen als markiert markiert "ausgewählt" und aktualisieren Sie den Inhalt der Seite).

Mit Node.js ist es so einfach wie im clientseitigen JavaScript-Code. Holen Sie sich Ihren DOM-Knoten und wenden Sie Ihre CSS-Klasse darauf an. Holen Sie sich Ihren DOM-Knoten und innerHTML Ihren Inhalt (dazu benötigen Sie zusätzlichen JavaScript-Code. Lesen Sie den Artikel, um mehr zu erfahren).

Ein weiteres gutes Beispiel ist, dass Sie Ihre Webseite mit JavaScript kompatibel machen können, das mit demselben Code ein- oder ausgeschaltet wird. Stellen Sie sich vor, Sie haben eine Datumsauswahl in JavaScript, mit der Ihre Benutzer jedes Datum mithilfe eines Kalenders abrufen können. Sie können denselben JavaScript-Code schreiben (oder verwenden), damit er mit ein- oder ausgeschaltetem JavaScript funktioniert.


7

Es gibt eine sehr gute Fast-Food-Analogie, die das ereignisgesteuerte Modell von Node.js am besten erklärt. Weitere Informationen finden Sie im vollständigen Artikel Node.js, Arztpraxen und Fast-Food-Restaurants - Grundlegendes zur ereignisgesteuerten Programmierung

Hier ist eine Zusammenfassung:

Wenn der Fast-Food-Laden einem traditionellen fadenbasierten Modell folgt, bestellen Sie Ihr Essen und warten in der Schlange, bis Sie es erhalten. Die Person hinter Ihnen kann erst bestellen, wenn Ihre Bestellung abgeschlossen ist. In einem ereignisgesteuerten Modell bestellen Sie Ihr Essen und müssen dann warten. Alle anderen können dann frei bestellen.

Node.js ist ereignisgesteuert, aber die meisten Webserver sind threadbasiert. York erklärt, wie Node.js funktioniert:

  • Sie verwenden Ihren Webbrowser, um eine Anforderung für "/about.html" auf einem Node.js-Webserver zu stellen.

  • Der Node.js-Server akzeptiert Ihre Anfrage und ruft eine Funktion zum Abrufen dieser Datei von der Festplatte auf.

  • Während der Node.js-Server auf das Abrufen der Datei wartet, wird die nächste Webanforderung bearbeitet.

  • Wenn die Datei abgerufen wird, wird eine Rückruffunktion in die Serverwarteschlange von Node.js eingefügt.

  • Der Node.js-Server führt diese Funktion aus, die in diesem Fall die Seite "/about.html" rendert und an Ihren Webbrowser zurücksendet.


6

Nun, ich verstehe das

  • Das Ziel von Node ist es, eine einfache Möglichkeit zum Erstellen skalierbarer Netzwerkprogramme bereitzustellen.
  • Node ähnelt im Design Systemen wie Ruby's Event Machine oder Python's Twisted und wird von diesen beeinflusst.
  • Evented I / O für V8-Javascript.

Für mich bedeutet das, dass Sie in allen drei Annahmen richtig waren. Die Bibliothek sieht vielversprechend aus!


1
Viele Male, die ich über Seite finde, ist ziemlich vage.
Jeff

6

Vergessen Sie auch nicht zu erwähnen, dass Googles V8 SEHR schnell ist. Es konvertiert tatsächlich den JavaScript-Code in Maschinencode mit der angepassten Leistung der kompilierten Binärdatei. Zusammen mit all den anderen großartigen Dingen ist es Wahnsinnig schnell.


3

F: Das Programmiermodell ist ereignisgesteuert, insbesondere die Art und Weise, wie es mit E / A umgeht .

Richtig. Es werden Rückrufe verwendet, sodass bei jeder Anforderung zum Zugriff auf das Dateisystem eine Anforderung an das Dateisystem gesendet wird und Node.js dann mit der Verarbeitung der nächsten Anforderung beginnt. Es würde sich nur um die E / A-Anforderung kümmern, wenn es eine Antwort vom Dateisystem erhält. Zu diesem Zeitpunkt wird der Rückrufcode ausgeführt. Es ist jedoch möglich, synchrone E / A-Anforderungen zu stellen (dh Anforderungen zu blockieren). Es ist Sache des Entwicklers, zwischen asynchron (Rückruf) oder synchron (Warten) zu wählen.

F: Es verwendet JavaScript und der Parser ist V8.

Ja

F: Es kann leicht zum Erstellen gleichzeitiger Serveranwendungen verwendet werden.

Ja, obwohl Sie ziemlich viel JavaScript von Hand codieren müssten. Es ist möglicherweise besser, sich ein Framework wie http://www.easynodejs.com/ anzusehen, das eine vollständige Online-Dokumentation und eine Beispielanwendung enthält.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.