Swi*_*ift 6 javascript nonblocking event-loop node.js
我有以下使用Node.js的简单http服务器:
var http = require('http');
var server = http.createServer(function(req, res) {
var counter = 0;
for(var i = 1; i <= 30; i++) {
http.get({ host: "www.google.com" }, function(r) {
counter++;
res.write("Response " + counter + ": " + r.statusCode + "\n");
if(counter == 30) res.end();
});
}
});
server.listen(8000);
Run Code Online (Sandbox Code Playgroud)
当我在端口8000上卷入我的本地主机时,我确实得到了预期的结果:
Response 1: 200
Response 2: 200
Response 3: 200
...
Response 30: 200
Run Code Online (Sandbox Code Playgroud)
但是当我在第一个进程运行时尝试从另一个终端卷入时,我看到控制台挂起并等待第一个进程完全完成,然后才开始接收相同的输出.
我的理解是,由于这是使用回调的异步代码,节点可以通过在事件循环的下一个滴答处理它们来同步处理多个请求.事实上,我甚至还观看过Ryan Dahl的视频,其中有一个类似于hello world的例子.我的代码中有什么东西可以阻止服务器阻塞?
您的问题与阻止呼叫没有任何关系; 这与您只能一次打开一定数量的连接到单个主机的事实有关.一旦达到最大打开连接数,其他异步调用http.get必须等到打开的连接数再次下降,这在其他请求完成并且其回调被触发时发生.由于您创建新请求的速度超过了他们消耗的速度,因此您可能会看到阻塞的结果.
这是我为测试此程序而创建的程序的修改版本.(请注意,有一种更简单的方法来解决您的问题,正如mtomis所示 - 更多内容如下所示.)我添加了一些console.log日志记录,因此更容易分辨处理内容的顺序; 我也拒绝除了以外的所有请求/,以便favicon.ico忽略请求.最后,我向许多不同的网站发出请求.
var http = require('http');
// http://mostpopularwebsites.net/1-50/
var sites = [
"www.google.com", "www.facebook.com", "www.youtube.com",
"www.yahoo.com", "www.blogspot.com", "www.baidu.com", "www.live.com",
"www.wikipedia.org", "www.twitter.com", "www.qq.com", "www.msn.com",
"www.yahoo.co.jp", "www.sina.com.cn", "www.google.co.in", "www.taobao.com",
"www.amazon.com", "www.linkedin.com", "www.google.com.hk",
"www.wordpress.com", "www.google.de", "www.bing.com", "www.google.co.uk",
"www.yandex.ru", "www.ebay.com", "www.google.co.jp", "www.microsoft.com",
"www.google.fr", "www.163.com", "www.google.com.br",
"www.googleusercontent.com", "www.flickr.com"
];
var server = http.createServer(function(req, res) {
console.log("Got a connection.");
if(req.url != "/") {
console.log("But returning because the path was not '/'");
res.end();
return;
}
var counter = 0;
for(var i = 1; i <= 30; i++) {
http.get({ host: sites[i] }, function(index, host, r) {
counter++;
console.log("Response " + counter + " from # " + index + " (" + host + ")");
res.write("Response " + counter + " from # " + index + " (" + host + ")\n");
if(counter == 30) res.end();
}.bind(this, i, sites[i]));
}
console.log("Done with for loop.");
});
server.listen(8000);
Run Code Online (Sandbox Code Playgroud)
我跑这个程序,并很快在两个不同的浏览器访问该页面(我也刷新我的DNS缓存,作为供试品正在运行太快,否则得到很好的输出).这是输出:
Got a connection.
Done with for loop.
Response 1 from # 8 (www.twitter.com)
Response 2 from # 1 (www.facebook.com)
Response 3 from # 12 (www.sina.com.cn)
Response 4 from # 4 (www.blogspot.com)
Response 5 from # 13 (www.google.co.in)
Response 6 from # 19 (www.google.de)
Response 7 from # 26 (www.google.fr)
Response 8 from # 28 (www.google.com.br)
Response 9 from # 17 (www.google.com.hk)
Response 10 from # 6 (www.live.com)
Response 11 from # 20 (www.bing.com)
Response 12 from # 29 (www.googleusercontent.com)
Got a connection.
Done with for loop.
Response 13 from # 10 (www.msn.com)
Response 14 from # 2 (www.youtube.com)
Response 15 from # 18 (www.wordpress.com)
Response 16 from # 16 (www.linkedin.com)
Response 17 from # 7 (www.wikipedia.org)
Response 18 from # 3 (www.yahoo.com)
Response 19 from # 15 (www.amazon.com)
Response 1 from # 6 (www.live.com)
Response 2 from # 1 (www.facebook.com)
Response 3 from # 8 (www.twitter.com)
Response 4 from # 4 (www.blogspot.com)
Response 20 from # 11 (www.yahoo.co.jp)
Response 21 from # 9 (www.qq.com)
Response 5 from # 2 (www.youtube.com)
Response 6 from # 13 (www.google.co.in)
Response 7 from # 10 (www.msn.com)
Response 8 from # 24 (www.google.co.jp)
Response 9 from # 17 (www.google.com.hk)
Response 10 from # 18 (www.wordpress.com)
Response 11 from # 16 (www.linkedin.com)
Response 12 from # 3 (www.yahoo.com)
Response 13 from # 12 (www.sina.com.cn)
Response 14 from # 11 (www.yahoo.co.jp)
Response 15 from # 7 (www.wikipedia.org)
Response 16 from # 15 (www.amazon.com)
Response 17 from # 9 (www.qq.com)
Response 22 from # 5 (www.baidu.com)
Response 23 from # 27 (www.163.com)
Response 24 from # 14 (www.taobao.com)
Response 18 from # 5 (www.baidu.com)
Response 19 from # 14 (www.taobao.com)
Response 25 from # 24 (www.google.co.jp)
Response 26 from # 30 (www.flickr.com)
Response 20 from # 29 (www.googleusercontent.com)
Response 21 from # 22 (www.yandex.ru)
Response 27 from # 23 (www.ebay.com)
Response 22 from # 19 (www.google.de)
Response 23 from # 21 (www.google.co.uk)
Response 24 from # 28 (www.google.com.br)
Response 25 from # 25 (www.microsoft.com)
Response 26 from # 20 (www.bing.com)
Response 27 from # 30 (www.flickr.com)
Response 28 from # 22 (www.yandex.ru)
Response 28 from # 27 (www.163.com)
Response 29 from # 25 (www.microsoft.com)
Response 29 from # 26 (www.google.fr)
Response 30 from # 21 (www.google.co.uk)
Response 30 from # 23 (www.ebay.com)
Got a connection.
But returning because the path was not '/'
Run Code Online (Sandbox Code Playgroud)
正如你所看到的那样,除了我花费的时间之外Alt+Tab Enter,回调完全混合在一起 - 最好的异步,非阻塞I/O.
[编辑]
正如mtomis所提到的,每个主机可以打开的最大连接数可以通过全局配置http.globalAgent.maxSockets.只需将其设置为您希望每个主机能够处理的并发连接数,您观察到的问题就会消失.
Node.js对每个主机的客户端连接有限制(默认情况下每个主机有5个连接),如下所述:http://nodejs.org/docs/v0.5.4/api/http.html#agent.maxSockets
第二个卷曲过程挂起直到第一个卷曲过程完成的原因是因为第一个进程排队30个请求,其中5个可以同时处理,因此第二个进程的下30个请求无法处理,直到第一个进程完成完成.在您的示例中,如果您设置http.globalAgent.maxSockets = 60;,则将同时处理呼叫.
| 归档时间: |
|
| 查看次数: |
1825 次 |
| 最近记录: |