我正在研究一個節點性能的小演示,並且很驚訝地看到下面的例子,併發調用setTimeout
需要花費4秒而不是500ms。對setTimeout的併發調用導致比預期更多的延遲
以下代碼設置了一個非常簡單的express服務器,用於偵聽所有請求,並在稍後使用setTimeout
響應500毫秒。然後它有一個客戶端,通過傳遞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個呼叫在500毫秒後同時返回。
當express和http調用與setTimeout
結合使用時,可能會導致額外延遲的原因是什麼?
您正在經歷那些延遲[因爲事件隊列](http://stackoverflow.com/questions/19822668/what-exactly-is-a-node-js-event-loop-tick)。 –
我可以證實這些發現。亞歷克斯,這不是一個有用的評論:*所有*異步與事件隊列有關。說這是「因爲事件隊列」就好像在說「這是因爲編程」。無意義的。我懷疑Node中的定時器功能有某種「元隊列」。也就是說,在計時器隊列中,節點將採用接下來的五個可用計時器並計劃這些計時器進行處理。不知道,儘管...現在查看Node源代碼。 –
我收回我說的話:我不認爲它是'setTimeout'的限制(因爲Samuel在他的文章中說過,如果你沒有HTTP請求運行這個測試,它可以按預期工作)。所以這必須是HTTP/Express隊列問題。 –