考虑以下简单的 Node.js 应用程序:
var http = require('http');
http.createServer(function() { }).listen(8124); // Prevent process shutting down
var requestNo = 1;
var maxRequests = 2000;
function requestTest() {
http.request({ host: 'www.google.com', method: 'GET' }, function(res) {
console.log('Completed ' + (requestNo++));
if (requestNo <= maxRequests) {
requestTest();
}
}).end();
}
requestTest();
它一个接一个地向 google.com 发出 2000 个 HTTP 请求。问题是它到达请求 5 并暂停大约 3 分钟,然后继续处理请求 6 - 10,然后再暂停 3 分钟,然后请求 11 - 15,暂停,依此类推。编辑: 我尝试将 www.google.com 更改为 localhost,这是一个非常基本的 Node.js 应用程序,运行我的机器并返回“Hello world”,但我仍然会暂停 3 分钟。
现在我读到我可以增加连接池限制:
http.globalAgent.maxSockets = 20;
现在,如果我运行它,它会处理请求 1 - 20,然后暂停 3 分钟,然后请求 21 - 40,然后暂停,依此类推。
最后,经过一番研究,我了解到我可以通过设置agent: false
请求选项来完全禁用连接池:
http.request({ host: 'www.google.com', method: 'GET', agent: false }, function(res) {
...snip....
...它会很好地处理所有 2000 个请求。
我的问题,这样做是个好主意吗?是否存在可能导致 HTTP 连接过多的危险?为什么它会暂停 3 分钟,当然,如果我已经完成连接,它应该直接将其添加回池中,为下一个请求使用做好准备,那么为什么要等待 3 分钟呢?原谅我的无知。
如果做不到这一点,对于 Node.js 应用程序发出可能大量的 HTTP 请求,而不会锁定或崩溃的最佳策略是什么?
我在 Mac OSX 10.8.2 上运行 Node.js 版本 0.10。
编辑:我发现如果我将上面的代码转换为一个 for 循环并尝试同时建立一堆连接,我在大约 242 个连接后开始出现错误。错误是:
Error was thrown: connect EMFILE
(libuv) Failed to create kqueue (24)
...和代码...
for (var i = 1; i <= 2000; i++) {
(function(requestNo) {
var request = http.request({ host: 'www.google.com', method: 'GET', agent: false }, function(res) {
console.log('Completed ' + requestNo);
});
request.on('error', function(e) {
console.log(e.name + ' was thrown: ' + e.message);
});
request.end();
})(i);
}
我不知道一个负载很重的 Node.js 应用程序是否可以同时达到这么多连接。