同时调用setTimeout会导致比预期更多的延迟
我正在做一个Node性能的小演示,很惊讶地发现下面的例子中,有50个setTimeout
并发调用需要4秒而不是500ms。
下面的代码设置了一个非常简单的express服务器,它侦听所有请求,并在稍后使用setTimeout
来响应500ms。 然后它有一个客户端,通过传递50个请求来跟踪请求和相应的响应。
// SERVER var express = require('express'); var app = express(); app.get('*', function (req, res) { setTimeout(function () { return res.send(req.query.i); }, 500); }); app.listen(8099); // CLIENT var http = require('http'); function start() { for (var i = 0; i < 50; i++) { console.log(new Date().getSeconds() + ':' + new Date().getMilliseconds() + ' - Sending ' + i); http.get('http://localhost:8099?i=' + i, responseHandler); } function responseHandler(res) { res.on('data', function (body) { return console.log(new Date().getSeconds() + ':' + new Date().getMilliseconds() + ' - Received ' + body); }); } } start();
我希望代码需要30-50ms才能完成所有setTimeout
调用,然后在500ms之后,所有这些代码都会在同一时间响应。 相反,我看到他们以5人一组来回答,每组5人之间有500毫秒。
我尝试了一些更简单的替代方法,它们都可以解决这个问题。 如果我拿setTimeout
并立即回应,所有的50个回应在100ms内进来。 如果我把Web服务器排除在外,并且只有50个setTimeout
调用,那么所有的50个调用都会立即排队,所有的50个调用在500ms之后同时返回。
当express和http调用与setTimeout
结合使用时,可能会导致额外的延迟?
这个问题与setTimeout
没有任何关系(因为您可能已经猜到了当你没有客户端/服务器设置的情况下运行你的testing)。 问题是Node http
服务器在任何给定时间处理的开放HTTP套接字的数量。
控制此设置的设置是Agent.maxSockets
(有关更多信息,请参阅文档 )。
maxSockets
的默认值是五。 所以,如果你发送50个请求到你的应用程序,它将一次处理5个请求, 直到它们完成,然后再转到新的请求。 因为在setTimeout
函数调用它们的callback函数之前它们不能完成,所以你的请求会以大约每500毫秒5次的突发速度响应。
如果你想certificate这一点,你所要做的就是改变maxSockets
的值:
http.globalAgent.maxSockets = 10;
现在,您将看到请求以10个连发处理。 如果将其设置为50,则应该看到您要查找的行为。
请注意,它可能设置为5的一个很好的理由,所以我不认为你的问题的“解决scheme”只是将maxSockets
设置为Infinity
或类似的东西。
mscdex在注释中指出你可以在http.request
指定一个cusotm代理,并且在Node v0.12中将会改变默认的maxSockets。