5

我们正在实现一个 node.js 服务器来获取网页和资产,通常是并行的,并将它们保存到 s3。似乎非常适合节点。仅供参考,我们在 aws ebs 上运行节点 v0.8.25,因为 v0.10 在 ebs 上不稳定,我们无法使其可靠地构建。然而,让我们适应的东西是古老的:

Error: connect ECONNRESET
at errnoException (net.js:770:11)
at Object.afterConnect [as oncomplete] (net.js:761:19)

我们从 mikeal 的请求库开始,它处理 303、缓冲和其他开箱即用的细节。现在原型已经完成,我们在缩放它时遇到了麻烦。在 4 或 5 页时,它开始抛出上述错误。我们将 globalAgents 设置为 1,000,将代理(请求池)设置为 false,以及许多其他配置选项。没爱。

然后我们做了一些额外的研究,并通过子堆栈找到了 Hyperquest。流式传输很困难,因为我们不想指望内容长度标头,但如果它可以扩展,我们愿意试一试。Substack 有一个漂亮的测试套件,可以将请求与超请求进行比较:

要求:

var http = require('http');
var request = require('request');
var startTime = (new Date()).getTime();

var server = http.createServer(function (req, res) {
    res.write(req.url.slice(1) + '\n');
    setTimeout(res.end.bind(res), 3000);
});

server.listen(5000, function () {
    console.log('starting test at ' + (Date.now() - startTime));
    var pending = 100;
    for (var i = 0; i < 100; i++) {
        var r = request('http://localhost:5000/' + i, {pool: false});
        r.pipe(process.stdout, { end: false });
        r.on('end', function () {
            if (--pending === 0) {
                server.close();
                console.log('ending test at ' + (Date.now() - startTime));
            }
        });
    }
});

process.stdout.setMaxListeners(0); // turn off annoying warnings

超任务:

var http = require('http');
var hyperquest = require('hyperquest');
var startTime = (new Date()).getTime();


var server = http.createServer(function (req, res) {
    res.write(req.url.slice(1) + '\n');
    setTimeout(res.end.bind(res), 3000);
});

server.listen(5000, function () {
    var pending = 200;
    for (var i = 0; i < 200; i++) {
        var r = hyperquest('http://localhost:5000/' + i);
        r.pipe(process.stdout, { end: false });
        r.on('end', function () {
            if (--pending === 0) server.close();
            console.log('ending test at ' + (Date.now() - startTime));            
        });
    }
});

process.stdout.setMaxListeners(0); // turn off annoying warnings

到目前为止,一切都很好。Hyperquest 运行时间超过 3 秒,请求需要 12 秒。然后我们设置 http.globalAgent.maxSockets = 1000 (或请求中的 pool: false ),对于 256 个请求,它们都在 3.229 秒内运行。

现在这是真正的问题和问题:如果将挂起的请求和循环增加到 257 或更多,两个库都会抛出以下错误:

    stream.js:81
      throw er; // Unhandled stream error in pipe.
            ^
Error: socket hang up
    at createHangUpError (http.js:1379:15)
    at Socket.socketCloseListener (http.js:1430:23)
    at Socket.EventEmitter.emit (events.js:96:17)
    at Socket._destroy.destroyed (net.js:358:10)
    at process.startup.processNextTick.process._tickCallback (node.js:245:9)

鉴于 256 有效,但不是 257,必须增加一些系统配置变量,但我找不到它,需要帮助。ulimit -n 是 2048,ulimit -a 是:

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 2048
pipe size            (512 bytes, -p) 1
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 709
virtual memory          (kbytes, -v) unlimited

任何帮助将不胜感激!

4

0 回答 0