Wie kann NodeJS "nicht blockierend" sein?

14

Ich lerne NodeJS und wollte nur etwas klarstellen. In einigen einführenden Tutorials und Büchern wurde bereits sehr früh die "nicht blockierende" Architektur von Node beschrieben - oder vielmehr, dass es möglich ist (und empfohlen wird, den gesamten Punkt), nicht blockierend zu codieren.

Dieses Beispiel wurde zum Beispiel in einem Buch gegeben, in dem ich eine asynchrone Methode zum Abrufen von Daten aus einer Datenbank lese.

http.createServer(function (req, res) {
  database.getInformation(function (data) {
      res.writeHead(200);
      res.end(data);
  });
});

Was passiert (so wie ich es verstehe) ist, dass Node den Aufruf an die Datenbank durchführt und dann die Verarbeitung dessen fortsetzt, was als nächstes auf dem Aufrufstapel stehen mag. Wenn die Datenbankanforderung abgeschlossen ist, wird die Datenvariable in der anonymen Rückruffunktion aufgefüllt und diese Funktion zum Aufrufstapel hinzugefügt (und anschließend ausgeführt, wenn der Knoten dazu gelangt).

Meine Frage ist, was genau verarbeitet die Datenbankanfrage? Sicherlich muss Node blocken, während es das tut? Was kümmert sich um die Datenbankanfrage? Oder wenn der Knoten auf eine asynchrone HTTP-GET-Anforderung an eine externe Ressource wartet, was kümmert sich dann um diese Anforderung, die es dem Knoten ermöglicht, den Aufrufstapel weiter zu verarbeiten und "nicht blockierend" zu sein?

Anonym
quelle

Antworten:

17

Wenn Node.js als "nicht blockierend" beschrieben wird, bedeutet dies speziell, dass sein IO nicht blockierend ist. Node verwendet libuv , um seine E / A plattformunabhängig zu behandeln. Unter Windows werden IO-Completion-Ports verwendet, unter Unix wird epoll / kqueue / select / etc verwendet. Es wird also eine nicht blockierende E / A-Anforderung gesendet (die möglicherweise im Hintergrund überwacht wird, jedoch niemals für JavaScript verfügbar ist) und bei einem Ergebnis in die Ereignisschleife eingereiht, die den JavaScript-Rückruf für das Hauptfenster aufruft (siehe: nur) JavaScript-Thread.

Bei Datenbanken hängt es davon ab, wie die Bibliothek geschrieben wurde. Wenn HTTP für die Kommunikation verwendet wird (wie dies bei einigen NoSQL-Datenbanken der Fall ist), kann dies mithilfe der Standardknotenbibliothek problemlos in reinem JavaScript geschrieben werden http. Wenn es anders geht, liegt das an der Bibliothek. Es könnte in C / C ++ geschrieben sein und Hintergrundthreads verwenden, solange diese Abstraktion niemals für JavaScript verfügbar gemacht wird.

In Bezug auf Ihre Frage, was die Datenbankanforderung "verarbeitet", müssen Sie im Idealfall nur eine einfache Nachricht an eine Bibliothek senden (z. B. eine SQL-Anweisung oder eine andere Abfrage oder eine Verbindungsanforderung) und an diesem Punkt Ihr JavaScript tuckert weiter. Wenn die Bibliothek bereit ist, eine Nachricht zurückzusenden, sendet sie eine Nachricht zurück an die Ereigniswarteschlange des Knotens, in der der Rückruf ausgeführt wird, sodass dieser Codeausschnitt ausgeführt werden kann.

ckknight
quelle
Es gibt das netPaket, wenn http nicht verfügbar ist.
Florian Margaine
Detail, das helfen könnte. Node nutzt den V8-JS-Motor. Eine der besten Funktionen von V8 ist die einfache Bindung von C / C ++ - Prozessen an JS-Aufrufe. JavaScript-Funktionen blockieren, aber eine Funktion ruft nur etwas unter der Haube auf, das nicht blockiert. Dann antwortet eine andere JS-Funktion, wenn dieser Vorgang abgeschlossen ist. JS-Funktionen, die sich gegenseitig blockieren, bedeuten, dass Sie niemals zwei Dinge gleichzeitig tun müssen, um einen Schreibvorgang für denselben Dateispeicherort zu planen. Es ist immer klar, welche Anfrage zuerst kam, um Dinge in die Warteschlange zu stellen.
Erik Reppen