2016-08-26 3 views
6

Ich bin eine Node.js App mit Express ausgeführt und möchte beginnen, die Leistung zu erhöhen. Mehrere Routen sind definiert. Nehmen wir ein einfaches Beispiel haben:node.js Leistungsoptimierung und Single-Threaded-Architektur

app.get('/users', function (req, res) { 
    User.find({}).exec(function(err, users) { 
     res.json(users); 
    } 
}); 

Nehmen wir an, wir haben 3 Kunden A, B und C, die versuchen, diesen Weg zu benutzen. Ihre Anfragen kommen auf dem Server in der Reihenfolge A, B, C mit einer Differenz von 1 Millisekunde dazwischen.

1. Wenn ich die Architektur von node.js richtig verstehe, wird jede Anfrage sofort bearbeitet, weil Users.find() asynchron ist und es nicht blockierenden Code gibt?

Lassen Sie sich dieses Beispiel mit einem synchronen Aufruf erweitern:

app.get('/users', function (req, res) { 
     var parameters = getUserParameters(); 

     User.find({parameters}).exec(function(err, users) { 
      res.json(users); 
     } 
    }); 

Gleiche Anfragen gleiche Reihenfolge. getUserParameters() dauert 50 Millisekunden.

2. A gibt die Route Callback-Funktion ein und blockiert den Thread node.js für 50 Millisekunden. B und C können die Funktion nicht eingeben und müssen warten. Wenn A getUsersParameters() beendet, wird es mit der asynchronen User.find() Funktion fortfahren und B wird nun die Route Callback-Funktion eingeben. C muss noch 50 Millisekunden warten. Wenn B die asynchrone Funktion eingibt, können die Anforderungen von C abschließend behandelt werden. Zusammengenommen: C muss 50 Millisekunden warten, bis A beendet ist, 50 Millisekunden, bis B beendet ist, und 50 Millisekunden, bis es beendet ist (der Einfachheit halber ignorieren wir die Wartezeit für die asynchrone Funktion).

Angenommen, wir haben eine weitere Route, die nur von einem Admin erreichbar ist und jede Minute über crontab aufgerufen wird.

app.get('/users', function (req, res) { 
    User.find({}).exec(function(err, users) { 
     res.json(users); 
    } 
}); 

app.get('/admin-route', function (req, res) { 
    blockingFunction(); // this function takes 2 seconds to complete 
}); 

3. Wenn eine Anfrage X trifft admin-route und blockingFunction() genannt wird, wird A, B und C, die /users direkt nach X Anfrage 2 Sekunden warten, haben rufen, bis sie auch die Rückruf-Funktion Route eingeben ?

4. Sollten wir jede selbstdefinierte Funktion, auch wenn sie nur 4 Millisekunden dauert, als asynchrone Funktion mit einem Callback ausführen?

+0

auf diese Frage Irrelevant, aber ich habe gehört, ist ausdrücklich tot. – WitVault

+0

Was wäre eine 'blockingFunction' in Node/JS? Afaik, alles ist um die Ereignisschleife herum modelliert. – Tobias

Antwort

6

Die Antwort ist "Ja", auf # 3: Blockieren bedeutet, dass die Ereignisschleife blockiert wird, was bedeutet, dass jede E/A (wie die Behandlung einer HTTP-Anfrage) blockiert wird. In diesem Fall scheint die App für diese 2 Sekunden nicht mehr zu reagieren.

Allerdings müssen Sie ziemlich wilde Dinge für synchronen Code tun, um 2 Sekunden dauern (entweder sehr schwere Berechnungen, oder mit vielen der *Sync() Methoden von Modulen wie fs zur Verfügung gestellt). Wenn Sie diesen Code wirklich nicht asynchron erstellen können, sollten Sie ihn in einem separaten Prozess ausführen.

In Bezug auf # 4: Wenn Sie es leicht asynchron machen können, sollten Sie wahrscheinlich. Wenn Sie Ihre synchrone Funktion jedoch nur dann annehmen lassen, wenn Sie einen Rückruf annehmen, wird dies auf wundersame Weise nicht asynchron. Es hängt davon ab, was die Funktion macht, wenn und wie Sie sie asynchron machen können.

0

Das Grundprinzip ist alles, was die CPU blockiert (lang andauernde für Schleifen zum Beispiel) oder irgendetwas, das I/O oder das Netzwerk verwendet, muss asynchron sein.Sie könnten auch in Betracht ziehen, die CPU-intensive Logik aus dem Knoten JS herauszunehmen, vielleicht in ein Java/Python-Modul, das einen WebService verfügbar macht, den JS aufrufen kann.

Nebenbei, werfen Sie einen Blick auf dieses Modul (möglicherweise nicht produktionsfertig). Es führt das Konzept von Multithreading in NodeJS: https://www.npmjs.com/package/webworker-threads

0

# 3 Ja

# 4 Node.js ist für Asynchron-Programmierung und seine damit eine gute diesem Ansatz folgen Überraschungen in der Leistung

Inzwischen Sie zu vermeiden, kann das Modul cluster von Node.js verwenden, um die Leistung und den Durchsatz Ihrer App zu verbessern.

0

Möglicherweise müssen Sie Ihre Anwendung zuerst vertikal skalieren. Überprüfen Sie das Node.js-Clustermodul. Sie können alle Kerne der Maschine nutzen, indem Sie Arbeiter auf jedem Kern hervorbringen. Ein Cluster ist ein Pool ähnlicher Worker, die unter einem übergeordneten Node-Prozess ausgeführt werden. Arbeiter werden mit der fork() -Methode des child_processes-Moduls erzeugt. Dies bedeutet, dass Mitarbeiter Serverhandles gemeinsam nutzen und Kommunikation zwischen Prozessen für die Kommunikation mit dem übergeordneten Node-Prozess verwenden können.

var cluster = require('cluster') 
 
var http = require('http') 
 
var os = require('os') 
 
var numCPUs = os.cpus().length 
 

 
if (cluster.isMaster) { 
 
    for (var i = 0; i < numCPUs; i++) { 
 
     cluster.fork() 
 
    } 
 
} else { 
 
    // Define express routes and listen here 
 
}