benschmaus / nodeload

HTTP load/traffic generator and benchmark tool built on Node.js
MIT License
399 stars 73 forks source link

nested requests #17

Open calarcon1 opened 12 years ago

calarcon1 commented 12 years ago

Hi, am trying to perform a test of a webserver using requestLoop.

The flow is like this:

Threre is a MAIN_REQUEST: * If success: I need to wait some time and trigger a SECONDARY request and then if success then I can consider it as SUCCESS

I was trying to achieve that by using the following function it the requestLoop:

function check_request(finished, client, url, index) {
    url = url + get_dev(index);

    var req = client.request('GET', url, { 'host': 'localhost', 'port': 8383 });
    req.on('response', function(res) {
        var body = '';
        var chunks = 0;
        res.setEncoding('utf8');
        res.on('data', function(data) {
            body = body + data.toString();
        });

        res.on('end', function() {
            if (body.indexOf("wait_retry") ==-1) {
                arr[index] = {status: 'BOOTING', wait: getRandomInt(0,max_boot_time)};
                //setTimeout(do_ack, arr[index].wait, client, index, finished, req, res);
                setTimeout(function() {
                    console.log("HOLA");
                    finished({req: req, res: res});
                }, 5000);
            } else {
                var sleep_regex = /sleep ([0-9]+)/m
                var sleep_array = body.match(sleep_regex);
                arr[index] = {status: 'WAITING', wait: parseInt(sleep_array[1],10)};
                res.statusCode = 301;
                finished({req: req, res: res});
                //setTimeout(check_request, arr[index].wait, finished, client, 'request', index, req);
            }
            console.log(url + " ******* " + arr[index].status);
            //finished({req: req, res: res});
        });
}

It seems that no new request is launched until finished is called. Is there a way to make the requestLoop call async?, so requests are launched no matter if finieshed was called or not.

Regards

jonjlee commented 12 years ago

This can be done, but you'll have to collect stats yourself for them to be meaningful. Particularly, any statistic in lib/monitoring/collectors.js whose end() accesses http.req or http.res cannot be used directly (e.g. result-codes, uniques, ...). If you do not use these, then you can call finished() without any parameters. For example, examples/simpletest.ex.js could be rewritten as:

var http = require('http');
var nl = require('../nodeload');
console.log("Test server on localhost:9000.");
http.createServer(function (req, res) {
    res.writeHead((Math.random() < 0.8) ? 200 : 404, {'Content-Type': 'text/plain'});
    res.end('foo\n');
}).listen(9000);

var m = new nl.Monitor([
    'result-codes', 
    { name: 'latency', percentiles: [0.9, 0.99] },
    'concurrency',
    'uniques',
    { name: 'http-errors', successCodes: [200,404], log: 'http-errors.log' }
]);

var test = nl.run({
    name: 'Read',
    host: 'localhost',
    port: 9000,
    numUsers: 10,
    timeLimit: 600,
    targetRps: 500,
    stats: ['rps'],
    requestLoop: function(finished, client) {
        var ctx = m.start();
        var req = client.request('GET', "/" + Math.floor(Math.random()*8000), { 'host': 'localhost' });
        req.on('response', function(res) {
            res.on('end', function() {
                ctx.end({req: req, res: res});
            });
        });
        req.end();
        finished();
    }
});

//
// These next lines are important to make the monitor's stats show up in the report...
//
test.on('update', function() { m.update(); });
nl.REPORT_MANAGER.getReport('Read').updateFromMonitor(m);