Node.js出站http请求并发性



我有一个node.js脚本,从本地存储的外部web API中提取数据。第一个请求是一个查询,它返回我需要获得进一步信息的id列表。对于返回的每个ID,我从node.js生成一个新的http请求,并向服务器获取数据(POST请求)。一旦工作完成,我就睡3分钟,然后重复。有时id的数量是数百个。每个单独的http请求可能返回1kb的数据,通常更少,所以往返路程非常短。

今天早上我收到一封来自API提供商的电子邮件,请求我关闭我的进程,因为我"用数百个连接占用了所有的API服务器"(这实际上我很自豪,但这不是重点)。为了友好起见,我把睡眠时间从3分钟增加到30分钟,到目前为止,这对他们有帮助。 关于这个问题……现在我没有设置maxSockets之类的,所以我认为默认值是5。这难道不意味着我一次只能创建5个实时http请求连接吗?管理员怎么会有几百人?他们的服务器在数据传递后没有挂起连接吗?难道我没有这样做吗?在我的http请求结束时,我没有明确的断开连接,所以也许我在这里有错。那么maxSockets实际上是什么呢?

对不起,由于某种原因,我没有正确阅读你的问题

maxSockets是http模块为当前进程创建的最大连接数。你可以通过http.globalAgent.maxSockets访问它来查看你的当前设置。

您可以使用以下命令查看有关当前与给定主机的连接数的一些信息:

console.log("Active socket connections: %d", http.globalAgent.sockets['localhost:8080'].length )
console.log("Total queued requests: %d", http.globalAgent.requests['localhost:8080'].length)

localhost:8080替换为您正在发出请求的任何主机和端口。

您可以在以下两点看到node如何处理这些连接:

添加新连接并存储到请求队列

https://github.com/joyent/node/blob/master/lib/_http_agent.js L83

从队列请求中创建连接

https://github.com/joyent/node/blob/master/lib/_http_agent.js L148


我很快地写了这篇文章,让你知道如何错开这些请求。这段特殊的代码不检查有多少请求正在"挂起",你可以很容易地修改它,让你在任何给定的时间只有一组请求发出(老实说,这将是更好的方法)。

var Stagger = function (data, stagger, fn, cb) {
    var self        = this;
    this.timerID    = 0;
    this.data       = [].concat(data);
    this.fn         = fn;
    this.cb         = cb;
    this.stagger    = stagger;
    this.iteration  = 0;
    this.store      = {};
    this.start = function () {
        (function __stagger() {
            self.fn(self.iteration, self.data[self.iteration], self.store);
            self.iteration++;
            if (self.iteration != self.data.length)
                self.timerID = setTimeout(__stagger, self.stagger);
            else
                cb(self.store);
        })();
    };
    this.stop = function () {
        clearTimeout(self.timerID);
    };
};

var t = new Stagger([1,2,3,4,5,6], 1000, function (i, item, store) {
    console.log(i, item);
    if (!store.out) store.out = [];
    store.out[i] = Math.pow(2,i);
},
function (store) {
    console.log('Done!', store);
});
t.start();

这段代码肯定可以改进,但它应该给你一个想法,也许从哪里开始。

实时演示:http://jsbin.com/ewoyik/1/edit(注意:需要控制台)

最新更新