【问题标题】:Why are my requests being paused when they're in a loop?为什么我的请求在循环中被暂停?
【发布时间】:2014-01-23 22:30:53
【问题描述】:

我正在尝试测试我正在阅读的书“Learning Node 2012”中的一些示例。我通过执行 2000 个请求来测试服务器的应用程序正在暂停。测试器在 5 个请求后暂停,并在一定间隔后再发送 5 个。为什么会暂停?我该如何解决这个问题?

服务器代码:

var http = require('http');
var fs = require('fs');

// write out numbers
var counter = 0;
function writeNumbers(res)
{

        for (var i = 0; i < 100; i++)
        {
                counter++;
                res.write(counter.toString() + '\n');
        }
}

// create the http server
http.createServer( function(req, res) {
        var query = require('url').parse(req.url).query;
        var app = require('querystring').parse(query).file + ".txt";

        // content header
        res.writeHead(200, { 'Content-Type': 'text/plain' } );

        // write out numbers
        writeNumbers(res);
        // timer to open file and read contents
        setTimeout(function() {
                console.log('opening ' + app);
                // open and read in file contents
                fs.readFile(app, 'utf8', function(err, data) {
                        if (err)
                                res.write('Could not find or open file for reading\n');
                        else
                                res.write(data);
                        res.end();
                });
        }, 2000);
}).listen(3000);

console.log('Server is running on port 3000');

垃圾邮件测试代码:

var http = require('http');

// the url we want, plus the path and options we need
var options = {
        host: 'localhost',
        port: 3000,
        path: '/?file=secondary',
        method: 'GET'
};

var processPublicTimeline = function(response) {
        // finished? ok, write the data to a file
        console.log('finished request');
};

for (var i = 0; i < 2000; i++)
{
        // make the request, and then end it, to close the connection
        http.request(options, processPublicTimeline).end();
}

【问题讨论】:

标签: node.js


【解决方案1】:

虽然这肯定与Why is node.js only processing six requests at a time? 有一些关系

这也是因为您使用timeOut 调用res.end() 来关闭连接/响应,从而移动到队列中的下一个连接。

您应该异步地考虑这些类型的事情,不要使用timeOuts,而是使用callBacks

所以你的两个主要块的代码可能更像:

var counter = 0;
function writeNumbers(res, callBack){
    // notice callBack argument

    for (var i = 0; i < 100; i++){
        counter++;
        res.write(counter.toString() + '\n');
    }

    // execute callBack (if it exists)
    if(callBack && typeof callBack === "function") callBack();
}

http.createServer( function (req, res){
    var query = require('url').parse(req.url).query;
    var app = require('querystring').parse(query).file + ".txt";

    res.writeHead(200, { 'Content-Type': 'text/plain' } );

    writeNumbers(res, function(){

        // Notice this function which is passed as a callBack argument for writeNumbers to evaluate.
        // This executes when the main writeNumbers portion finishes.

        console.log('opening ' + app);

        fs.readFile(app, 'utf8', function(err, data) {
            if (err)
                res.write('Could not find or open file for reading\n');
            else
                res.write(data);
            res.end();
        });
    });

}).listen(3000);

请注意,您的writeNumbers 函数现在需要一个callBack 参数在完成时执行,并且当您在服务器的对象中调用它时,您将一个函数作为callBack 参数传递。这是 node.js/javascript 应用程序中非常常用的核心模式之一。

这意味着您无需等待timeOut 执行来结束您的请求响应,而是在它处理您的响应时结束,并立即进入下一个连接。这可能会比 2 秒快(你的timeOut 的数量)。因此,您应该会看到您的连接被更快地处理。

因为(正如有人在您的 cmets 中指出的那样)您的系统一次只能处理几个打开的 TCP 连接,您希望尽快通过连接。当您想按特定顺序执行操作时,或者如果您需要等待某些进程完成后再执行其他进程时,利用回调链可以帮助您做到这一点,而无需使用 timeOut 进行猜测。

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多