用 node.js 自製一個類似 ab 的小巧工具~
需要 v0.6 以上支援的 cluster。
工作原理是建立一群 worker pool,同時去連個網站,work 工作完成以後再跑下一次,猜測應當是跟 ab 的作法差不多?!
目前預設參數是
url : www.yahoo.com.tw
times : 1000
numCPUs : 你電腦邏輯核心數(假設是 16)
就等同於跑
$ ab -c 16 -n 1000 www.yahoo.com.tw/
耗費的時間是不太一樣~實作有差吧~
[mlwmlw@amlw ~]$ node nb.js Completed 100 requests Completed 200 requests Completed 300 requests Completed 400 requests Completed 500 requests Completed 600 requests Completed 700 requests Completed 800 requests Completed 900 requests Finished 1000 requests Time per request:27.096ms Time taken for tests:27.096s
var cluster = require('cluster'); var http = require('http'); var numCPUs = require('os').cpus().length; var url = 'www.yahoo.com.tw'; var times = 1000; if (cluster.isMaster) { // Fork workers. var workers = []; var counter = 0; var start; for (var i = 0; i < numCPUs; i++) { workers[i] = cluster.fork(); workers[i].work = 0; workers[i].on("message", (function(num) { return function(msg) { if(msg.cmd == 'done') { workers[num].work ++; counter++; //finish if(counter >= times) { var end = new Date(); for(var j=0; j<numCPUs; j++) { //console.log('workers[' + j +']' + ' was finished ' + workers[j].work +' job'); workers[j].send({'cmd': 'exit'}); workers[j].emit('exit'); } console.log('Finished ' + times + ' requests'); console.log('Time per request:' + ((end-start)/times) + 'ms'); console.log('Time taken for tests:' + ((end - start)/1000) + 's'); } else { if(counter % 100 == 0) { console.log('Completed ' + counter + ' requests'); } workers[num].send({'cmd': 'work'}); } } } })(i)); } //ready start = new Date(); for (var k = 0; k < numCPUs; k++) { workers[k].send({'cmd': 'work'}); } cluster.on('death', function(worker) { //console.log('worker ' + worker.pid + ' died'); }); } else { // Worker processes have a http . var options = { host: url, port: 80 }; var alive = true; process.on('message', function(msg) { if(msg.cmd == 'exit') { alive = false; } else if(msg.cmd == 'work'){ http.get(options, function(res) { res.on('data', function (chunk) { }); res.on('end', function() { if(alive) process.send({'cmd' : 'done'}); }); }).on('error', function(e) { if(alive) process.send({'cmd' : 'failed'}); }); } }); }