2014-01-20 3 views
16

Ich mache einen schnellen Leistungstest für NodeJS vs. Java. Der ausgewählte einfache Anwendungsfall ist das Abfragen einer einzelnen Tabelle in der MySQL-Datenbank. Die ersten Ergebnisse waren wie folgt:Wie skaliere ich NodeJS linear auf mehreren Kernen?

Platform      | DB Connections | CPU Usage | Memory Usage | Requests/second 
==============================|================|===========|===============|================ 
Node 0.10/MySQL    | 20    | 34%  | 57M   | 1295 
JBoss EAP 6.2/JPA    | 20    | 100%  | 525M   | 4622 
Spring 3.2.6/JDBC/Tomcat 7.0 | 20    | 100%  | 860M   | 4275 

Beachten Sie, dass Knoten der CPU- und Speichernutzung sind viel niedriger als Java, aber der Durchsatz ist auch etwa ein Drittel! Dann stellte ich fest, dass Java alle vier Kerne auf meiner CPU verwendete, während Node auf nur einem Kern lief. Also änderte ich den Node-Code, um das Cluster-Modul zu integrieren, und jetzt nutzte er alle vier Kerne. Hier sind die neuen Ergebnisse:

Platform      | DB Connections | CPU Usage | Memory Usage | Requests/second 
==============================|================|===========|===============|================ 
Node 0.10/MySQL (quad core) | 20 (5 x 4)  | 100%  | 228M (57 x 4) | 2213 

Beachten Sie, dass die CPU- und Speicherauslastung haben nun proportional gestiegen, aber der Durchsatz nur um 70% gestiegen ist. Ich habe eine vierfache Steigerung erwartet und den Java-Durchsatz überschritten. Wie kann ich die Abweichung erklären? Was kann ich tun, um den Durchsatz linear zu erhöhen?

Hier ist der Code für die Nutzung mehrerer Kerne:

if (Cluster.isMaster) { 
    var numCPUs = require("os").cpus().length; 
    for (var i = 0; i < numCPUs; i++) { 
     Cluster.fork(); 
    } 

    Cluster.on("exit", function(worker, code, signal) { 
     Cluster.fork(); 
    }); 
} 
else { 
    // Create an express app 
    var app = Express(); 
    app.use(Express.json()); 
    app.use(enableCORS); 
    app.use(Express.urlencoded()); 

    // Add routes 

    // GET /orders 
    app.get('/orders', OrderResource.findAll); 

    // Create an http server and give it the 
    // express app to handle http requests 
    var server = Http.createServer(app); 
    server.listen(8080, function() { 
     console.log('Listening on port 8080'); 
    }); 
} 

Ich bin der Knoten-mysql-Treiber für die Abfrage der Datenbank. Der Verbindungspool ist auf 5 Verbindungen pro Kern festgelegt, dies macht jedoch keinen Unterschied. Wenn ich diese Zahl auf 1 oder 20 setze, bekomme ich ungefähr den gleichen Durchsatz!

var pool = Mysql.createPool({ 
    host: 'localhost', 
    user: 'bfoms_javaee', 
    password: 'bfoms_javaee', 
    database: 'bfoms_javaee', 
    connectionLimit: 5 
}); 

exports.findAll = function(req, res) { 
    pool.query('SELECT * FROM orders WHERE symbol="GOOG"', function(err, rows, fields) { 
     if (err) throw err; 
     res.send(rows); 
    }); 
}; 
+0

Sie könnten versuchen 'NODE_ENV = production' https://groups.google.com/forum/#!topic/express-js/fqtr1Carr0E – KeepCalmAndCarryOn

+0

Sind Sie auch Pooling-Verbindungen richtig? Dies ist der vorgeschlagene Weg 'var mysql = require ('mysql'); var pool = mysql.createPool (...); pool.getConnection (Funktion (Fehler, Verbindung)) { // Verwenden Sie die Verbindung Verbindung.Abfrage ('SELECT etwas aus Somethable', Funktion (Fehler, Zeilen)) { // Und mit der Verbindung getan. connection.release(); // Verwenden Sie nicht die Verbindung hier, es wurde an die zurückgegeben Pool }); }); 'https://github.com/felixge/node-mysql – KeepCalmAndCarryOn

+0

Ja, ich benutze den Pool richtig. Der Code, den ich zeige, ist nur eine Abkürzung von dem, was Sie haben (ich habe es in beide Richtungen versucht). Dies wurde ausführlich in diesem Knoten-mysql Problem erläutert: https://github.com/felixge/node-mysql/issues/712. – Naresh

Antwort

1

Versuchen Sie, die Umgebungsvariable export NODE_CLUSTER_SCHED_POLICY="rr" Einstellung. Gemäß this blog post.

+0

Dieser Artikel spricht über die NodeJS-Version 0.12, die noch nicht unter http://nodejs.org/ verfügbar ist. Es sagt auch, dass der Round-Robin-Algorithmus die Leistung unter Windows nicht beeinflusst, wo ich meine Tests mache. – Naresh

+1

Ja, aber das gilt auch für aktuelle Versionen von v0.10. Es kompensiert jedoch insbesondere einen Aspekt des Schedulers des Linux-Kernels, so dass dies unter Windows nicht notwendig ist. –

2

Von dem, was ich sehe, vergleichen Sie nicht nur Plattformen, sondern auch die Frameworks. Wahrscheinlich möchten Sie den Framework-Effekt entfernen und einen einfachen HTTP-Server implementieren. Zum Beispiel addieren alle diese Middlewares in der Express-App die Latenz. Haben Sie auch sichergestellt, dass die Java-Bibliotheken die häufig angeforderten Daten nicht zwischenspeichern, was die Leistung erheblich verbessern würde?

Andere Dinge zu beachten ist, dass das eingebaute http Modul in Node (also jede Bibliothek darauf gebaut, einschließlich node-mysql) einen internen Verbindungspool über die Agent-Klasse (nicht mit dem MySQL-Verbindungspool zu verwirren)), damit HTTP-Keep-Alives verwendet werden können. Dies erhöht die Leistung, wenn Sie viele Anforderungen an denselben Server ausführen, anstatt eine TCP-Verbindung zu öffnen, eine HTTP-Anforderung zu stellen, eine Antwort zu erhalten, die TCP-Verbindung zu schließen und zu wiederholen. Somit können die TCP-Verbindungen wiederverwendet werden.

Standardmäßig öffnet der HTTP-Agent nur 5 gleichzeitige Verbindungen zu einem einzelnen Host, z. B. Ihrem MySQL-Server. Sie können dies leicht wie folgt ändern:

var http = require('http'); 
http.globalAgent.maxSockets = 20; 

diese Veränderungen betrachtet, sehen, welche Verbesserungen man bekommen kann.

Andere Ideen bestehen darin, zu überprüfen, ob der MySQL-Verbindungspool ordnungsgemäß verwendet wird, indem er überprüft, ob sich MySQL beim Öffnen und Schließen von Verbindungen anmeldet. Wenn sie häufig geöffnet werden, müssen Sie möglicherweise den Leerlaufzeitwert in Node-mysql erhöhen.

+0

Danke für die Ideen. Momentan konzentriere ich mich auf andere Dinge, habe aber eine Aufgabe, diese Vorschläge auszuprobieren. – Naresh

Verwandte Themen