2014-11-06 79 views
9

如果有人想尝试https://github.com/codependent/cluster-performanceNode.js的群集不显著提高性能

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

首先,我只用一个节点进程对它进行测试。对于第二次测试,我启动尽可能多的工人作为机器的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. 只有一个节点处理

这些是结果:

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个请求,不错。

  • Ñ工人(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; 
    

    UPDATE:

    我终于接受了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发行版,尽管您没有获得8x rps增量e,吞吐量几乎快了1.7倍。另一方面,如预期的那样,使用for循环迭代请求中指示的毫秒数(并因此阻塞线程),rps将与线程数成比例地增加。

    +0

    Amdahl定律指出,即使在最乐观的情况下,您将无法获得8次改良效果,你要寻找的。可能有很多可能的答案,为什么你的结果没有多大改善。你的应用程序要么不能很好地扩展,要么运行的服务器并没有真正的8 CPU可用等。 – user2717954 2014-11-07 08:05:28

    +0

    呵呵,我知道8x太乐观了。无论如何,有8个CPUS可以做一些工作,但实际上它应该改善rps,但它甚至不会使性能提高一倍。关于“你的应用程序不缩放”,以及你可以看到代码非常简单:带setTimeout()的路线,它怎么会不会缩放... – codependent 2014-11-07 12:04:18

    回答

    15

    I/O操作正是那种应用的Node.js的设计和优化。 I/O操作(和setTimeout)基本上与硬件(网络,磁盘,PCI桥,DMA控制器等)允许的并行运行。

    一旦你意识到这一点,这是很容易理解为什么在一个进程中运行许多并行I/O操作需要的时间大致相同数量的运行许多并行在许多进程/线程I/O操作。事实上,直接模拟将在一个进程中运行多个并行I/O操作,与在许多并行进程中运行单个阻塞I/O操作完全相同。

    集群允许你,如果你让他们使用多个CPU /核心。但是你的过程不使用CPU周期。所以集群给你很少的优势(如果有的话)。

    +0

    要查看聚类的优点,可以给CPU绑定应用程序中,用for循环替换setTimeout。 – slebetman 2015-02-26 08:21:30

    +0

    我会试一试并报告,谢谢你的信息! – codependent 2015-02-27 07:44:44

    0

    你试过拆分两个或多个进程之间的loadtesting程序本身?您完全有可能达到loadtest应用程序的极限。

    -1

    不要使用cluster.SCHED_RR,只需使用cluster.SCHED+

    +0

    添加一些解释和回答这个答案如何帮助OP在解决当前问题 – 2016-12-24 06:50:28

    0

    一个简单的计算:

    1000/20*220 = 11000 // theoretically max request per second 
    

    您测试本地主机上,这意味着使用网络时间是很小的,所以我想日志输出是阻止

    appLog.debug("Timeout completed %d", process.pid); 
    

    请评论并再试一次。