如何在多个核心上线性扩展NodeJS?

我正在做一个NodeJS与Java的快速性能testing。 所select的简单用例是查询MySQL数据库中的单个表。 初步结果如下:

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 

请注意,Node的CPU和内存使用率比Java低,但吞吐量也只有三分之一! 然后我意识到Java正在利用我的CPU上的所有四个核心,而Node只在一个核心上运行。 所以我改变了节点代码来整合集群模块,现在它正在利用所有四个核心。 以下是新的结果:

 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 

请注意,CPU和内存的使用量现在已经成比例增加,但吞吐量只上升了70%。 我预计会增加四倍,超过Java的吞吐量。 我怎样才能说明这个缺点? 我可以做什么来线性增加吞吐量?

以下是使用多核的代码:

 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'); }); } 

我使用node-mysql驱动来查询数据库。 连接池被设置为每个核心5个连接,但是没有区别。 如果我把这个数字设置为1或20,我可以得到大致相同的吞吐量!

 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); }); }; 

从我所看到的,你不仅仅比较平台,而且还比较框架。 您可能想要删除框架效果并实现普通的HTTP服务器。 例如,Express应用程序中的所有中间件都会增加延迟。 另外,您是否确保Java库不会caching频繁请求的数据,从而显着提高性能?

其他要考虑的事情是Node中的内置http模块(因此,任何build立在它上面的库,包括node-mysql )都通过Agent类维护一个内部连接池(不要与MySQL连接池混淆)它可以利用HTTP保持活力。 当您向同一服务器运行多个请求而不是打开TCP连接,发出HTTP请求,获取响应,closuresTCP连接并重复时,这有助于提高性能。 因此,TCP连接可以被重用。

默认情况下,HTTP代理将只能打开5个同时连接到单个主机,如MySQL服务器。 你可以很容易地改变这个如下:

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

考虑到这些变化,看看你可以得到什么改善。

其他的想法是通过在连接打开和closures时检查MySQL日志来validationMySQL连接池是否正确使用。 如果经常打开,则可能需要增加node-mysql中的空闲超时值。

尝试设置环境variablesexport NODE_CLUSTER_SCHED_POLICY="rr" 。 按照这个博客文章 。