Node.js集群不会显着提高性能
如果有人想尝试 : https : //github.com/codependent/cluster-performance
我正在用一个简单的应用程序testing每秒限制的Node.js(v0.11.13 – Windows 7)请求。 我已经使用Express 4实现了一个服务,它使用setTimeoutcallback来模拟I / O操作,如数据库查询。
首先,我只用一个节点进程testing它。 对于第二个testing,我开始尽可能多的工作人员的机器CPU。
我正在使用loadtest使用以下参数testing服务:
loadtest -n 50000 -c 220 -k http://localhost:5000/operations/timeout/20
也就是说,总共有5万个请求,有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')); });
- 只有一个节点进程
这是结果:
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个工人(n = numCPU)
在这种情况下,我使用循环调度策略在负载中平均分配负载。 由于现在有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发行版中,尽pipe你没有获得8倍的rps增长,但吞吐速度几乎快了1.7倍。
另一方面,如预期的那样,使用for循环迭代请求中指示的毫秒量(并因此阻塞线程),rps与线程数量成比例地增加。
I / O操作正是Node.jsdevise和优化的应用程序types。 I / O操作(和setTimeout)本质上与硬件(networking,磁盘,PCI桥,DMA控制器等)允许的并行运行。
一旦意识到这一点,就很容易理解为什么在单个进程中运行多个并行I / O操作的时间几乎与在许多进程/线程中运行许多并行I / O操作的时间相当。 事实上,直接模拟将在一个进程中运行多个并行I / O操作,与在许多并行进程中运行单个阻塞I / O操作完全相同。
集群允许您使用多个CPU /内核。 但是你的过程不使用CPU周期。 所以集群给你很less的优势(如果有的话)。
你有没有尝试在两个或多个进程之间分裂loadtesting程序本身? 您完全有可能达到loadtest应用程序的限制。
一个简单的计算:
1000/20*220 = 11000 // theoretically max request per second
你在本地主机上testing,这意味着使用的networking时间是微小的,所以我想日志输出是块
appLog.debug("Timeout completed %d", process.pid);
请评论并重试。
不要使用cluster.SCHED_RR
,只需使用cluster.SCHED+