首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在多核上线性扩展NodeJS?

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

Stack Overflow用户
提问于 2014-01-21 05:28:55
回答 2查看 1.2K关注 0票数 16

我正在对NodeJS和Java做一个快速的性能测试。选择的简单用例是查询MySQL数据库中的单个表。初步结果如下:

代码语言:javascript
复制
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的三分之一左右!然后我意识到Java在我的CPU上利用了所有四个核心,而Node只在一个核心上运行。因此,我更改了Node代码以合并集群模块,现在它利用了所有四个核心。以下是新的结果:

代码语言:javascript
复制
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吞吐量。我该如何解释这种肮脏呢?如何才能线性提高吞吐量?

下面是使用多核的代码:

代码语言:javascript
复制
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,我会得到大致相同的吞吐量!

代码语言:javascript
复制
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);
    });
};
EN

回答 2

Stack Overflow用户

发布于 2014-07-18 13:34:35

在我看来,你不仅在比较平台,还在比较框架。您可能希望消除框架效应,并实现一个普通的HTTP服务器。例如,Express应用程序中的所有这些中间件加起来就是延迟。另外,您是否确保Java库不会缓存频繁请求的数据,这会显著提高性能?

要考虑的其他事项是,Node中的内置http模块(因此,构建在它之上的任何库,包括node-mysql)通过代理类维护一个内部连接池(不要与MySQL连接池混淆),以便它可以利用HTTP keep-alives。当您对同一服务器运行多个请求而不是打开TCP连接、发出HTTP请求、获取响应、关闭TCP连接和重复时,这有助于提高性能。因此,TCP连接可以被重用。

默认情况下,HTTP代理只会同时打开5个到单个主机的连接,比如您的MySQL服务器。您可以按如下方式轻松更改此设置:

代码语言:javascript
复制
var http = require('http');
http.globalAgent.maxSockets = 20;

考虑到这些更改,看看您可以获得哪些改进。

其他的想法是通过检查MySQL连接何时打开以及何时关闭来验证MySQL连接池是否被正确使用。如果它们经常打开,您可能需要增加node-mysql中的空闲超时值。

票数 3
EN

Stack Overflow用户

发布于 2014-01-21 08:32:56

尝试设置环境变量export NODE_CLUSTER_SCHED_POLICY="rr"。根据this blog post

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21244512

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档