javascript - Node.js 集群并没有显着提高性能

标签 javascript node.js cluster-computing

如果有人想尝试: https://github.com/codependent/cluster-performance

我正在使用一个简单的应用程序测试 Node.js (v0.11.13 - Windows 7) 每秒请求限制。我已经使用 Express 4 实现了一项服务,该服务模拟 I/O 操作,例如带有 setTimeout 回调的数据库查询。

首先我只用一个 Node 进程对其进行测试。对于第二个测试,我启动与机器 CPU 一样多的工作人员。

我正在使用 loadtest使用以下参数测试服务:

loadtest -n 50000 -c 220 -k http://localhost:5000/operations/timeout/20

也就是说,总共有 50k 个请求,220 个并发客户端。

我的服务根据最后一个url参数(20 mseg)设置超时时间(处理时间的持续时间):

router.route('/timeout/:time')
.get(function(req, res) {
    setTimeout(function(){
        appLog.debug("Timeout completed %d", process.pid);
        res.json(200,{result:process.pid});
    },req.param('time'));
});    
  1. 只有一个 Node 进程

这些是结果:

INFO Max requests:        50000
INFO Concurrency level:   200
INFO Agent:               keepalive
INFO
INFO Completed requests:  50000
INFO Total errors:        0
INFO Total time:          19.326443741 s
INFO Requests per second: 2587
INFO Total time:          19.326443741 s
INFO
INFO Percentage of the requests served within a certain time
INFO   50%      75 ms
INFO   90%      92 ms
INFO   95%      100 ms
INFO   99%      117 ms
INFO  100%      238 ms (longest request)

每秒 2580 个请求,还不错。

  1. n 个 worker (n = numCPUs)

在这种情况下,我使用循环调度策略在工作人员之间平均分配负载。由于现在有 8 个内核处理请求,我预计每秒请求的结果会显着提高(快 8 倍?),但 它只增加到 2905 rps!!! (318 rps 以上) 你怎么解释呢?我做错了吗?

结果:

Max requests:        50000
Concurrency level:   220
Agent:               keepalive

Completed requests:  50000
Total errors:        0
Total time:          17.209989764000003 s
Requests per second: 2905
Total time:          17.209989764000003 s

Percentage of the requests served within a certain time
  50%      69 ms
  90%      103 ms
  95%      112 ms
  99%      143 ms
 100%      284 ms (longest request)

我的集群初始化代码:

#!/usr/bin/env node
var nconf = require('../lib/config');
var app = require('express')();
var debug = require('debug')('mma-nodevents');
var http = require("http")
var appConfigurer = require('../app');
var cluster = require('cluster');
var numCPUs = require('os').cpus().length;

if('v0.11.13'.localeCompare(process.version)>=0){
    cluster.schedulingPolicy = cluster.SCHED_RR;
}

if (cluster.isMaster) {
    // Fork workers.
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }
    cluster.on('exit', function(worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' died');
        cluster.fork();
    });
}else{
    console.log("starting worker [%d]",process.pid);
    appConfigurer(app);
    var server = http.createServer(app);
    server.listen(nconf.get('port'), function(){
        debug('Express server listening on port ' + nconf.get('port'));
    });

}

module.exports = app;

更新:

我终于接受了 slebetman 的回答,因为他对在这种情况下集群性能没有显着提高最多 8 个进程的原因是正确的。不过我想指出一个有趣的事实:对于当前的 io.js 版本 (2.4.0),即使对于这种高 I/O 操作 (setTimeout),它也确实得到了改进:

loadtest -n 50000 -c 220 -k http://localhost:5000/operations/timeout/20

单线程:

Max requests:        50000
Concurrency level:   220
Agent:               keepalive

Completed requests:  50000
Total errors:        0
Total time:          13.391324847 s
Requests per second: 3734
Total time:          13.391324847 s

Percentage of the requests served within a certain time
  50%      57 ms
  90%      67 ms
  95%      74 ms
  99%      118 ms
 100%      230 ms (longest request)

8核集群:

Max requests:        50000
Concurrency level:   220
Agent:               keepalive

Completed requests:  50000
Total errors:        0
Total time:          8.253544166 s
Requests per second: 6058
Total time:          8.253544166 s

Percentage of the requests served within a certain time
  50%      35 ms
  90%      47 ms
  95%      52 ms
  99%      68 ms
 100%      178 ms (longest request)

因此很明显,在当前的 io.js/node.js 版本中,尽管 rps 没有提高 8 倍,但吞吐量几乎快了 1.7 倍。

另一方面,正如预期的那样,使用 for 循环迭代请求中指示的毫秒数(并因此阻塞线程),rps 与线程数成比例增加。

最佳答案

I/O 操作正是 Node.js 设计和优化的那种应用程序。 I/O 操作(和 setTimeout)基本上是在硬件(网络、磁盘、PCI 桥、DMA Controller 等)允许的情况下并行运行。

一旦您意识到这一点,就很容易理解为什么在单个进程中运行许多并行 I/O 操作所花费的时间与在许多进程/线程中运行许多并行 I/O 操作所花费的时间大致相同。实际上,直接模拟在一个进程中运行多个并行 I/O 操作与在多个并行进程中运行单个阻塞 I/O 操作完全相同。

集群允许您使用多个 CPU/内核(如果有)。但是您的进程不使用 CPU 周期。所以集群给你的优势很小(如果有的话)。

关于javascript - Node.js 集群并没有显着提高性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26781371/

相关文章:

tomcat - 在不使 session 属性可序列化的情况下,是否可以在 tomcat 中进行 session 复制?

python - 使用 SLURM 请求 2 个 GPU 并运行 1 个 python 脚本

Javascript Tic Tac Toe Win Checker 很湿

node.js - 在 MongoDB 中每个集合使用多个地理空间索引

apache-spark - 错误 : path does not exist in spark submit with hadoop

javascript - 模型中的 Backbone 集合 + 使用 Node.js 的 Restful 服务器设计

node.js - NodeJS App.Get 订单错误

javascript - 从另一个action获取html代码并通过javascript操作该代码

javascript - JQuery 的 .load() 导致 HTML 结构错误

javascript - 在 href lnks 中使用 javascript void(0) 的替代方法是什么? (对于 Backbone 和 SPA 站点)